Permalink
Browse files

0.3.0 Development Release. See CHANGELOG for details.

  • Loading branch information...
1 parent 7b51877 commit eb4024e00aea6268b171690560fc728d6e43b0f4 Archibald Bell committed Jul 1, 2012
Showing with 282 additions and 97 deletions.
  1. +18 −0 CHANGELOG
  2. +8 −3 TODO
  3. +93 −46 app/handlers/remailer.py
  4. +26 −1 app/model/mixConfig.py
  5. +43 −24 app/model/mixKeystore.py
  6. +32 −2 app/model/mixPayload.py
  7. +7 −0 app/templates/adminkey.msg
  8. +55 −21 setup.py
View
@@ -1,3 +1,21 @@
+0.3.0
+ Integrate bugfix from Tom Ritter to fix bad Message Sending bug. Previously,
+ as the server ran, all messages would be delivered to all recipients
+ that had been seen so far.
+ Fix Header Field processing that would badly mess up messages with no
+ headers
+
+ Process Quicksilver Messages, which are formatted in a way inconsistent
+ with the Mixmaster spec. See mixPayload.py
+ Process remailer-adminkey
+ Process detination-block requests and do not send mail to them.
+ WARNING: The detination-block file writing is not thread-safe
+ Better prompts in setup.py, allow admin and abuse addresses to be addresses
+ on other domains. Try to get adminkey from keyring.
+
+ Add stubs for remailer-stats and remailer-conf
+ Stubs/Rearchitecting for downloading stats programmatically
+ Improve logging by outputing message UID with each line
0.2.1
Fix delivery to domains by using correct MX/A processing
0.2.0
View
11 TODO
@@ -26,21 +26,21 @@ TODO
Posting to Newsgroups
Duplicate Mail Detection (Sending duplicates is a feature of mixmaster
that should be supported, not an error condition to be checked.)
- Blocked Addresses
Doesn't reply with an explanation if it recieves a non-mix email
- Ensure remailer talks TLS over the SMTP links whenever possible
- Normalize logging. Make it a option chosen on setup
NSA logging - log all messages in and out
Debug logging - log messages that cause errors
Minimal logging - log almost nothing
- Right now any message with a destination of null: gets ignored. No one
- would mix a legit and a dummer recipient together... right?
+ would mix a legit and a dummy recipient together... right?
- lamson has very, very rudimentary support for skipping over .onion MX records
(because of frell). It'd be nice to fully support delivering to .onion
+ - destination-block file writing is not Thread-safe.
LONG TERM REMAILER REFRESHES
-These will break older mixes. They should only be done if there are serious
+These may break older mixes. They should only be done if there are serious
advantages of keeping the old protocol mostly-intact instead of moving to a
standard encrypted-wire-protocol of OpenPGP
@@ -50,3 +50,8 @@ standard encrypted-wire-protocol of OpenPGP
- Update its assumption that it is the only mixmaster implementation
rem.c : 175 : bufileft(content, "mixmaster")
+
+ - Give the option to send a confirmation message for destination-block address
+ - Require verification for destination-block addresses added to the list
+ - Have a shared database for all remailers of destination-block addresses.
+ Hash them to provide anonymity.
View
@@ -53,47 +53,91 @@ def REMAIL(message, to=None, suffix=None, host=None):
utils.mail_to_file(message, filename=messageId)
if subject == 'remailer-stats':
- logging.debug("Processing a remailer-stats request...")
- pass
+ logging.debug("Processing a remailer-stats request..." + messageId)
+ stats = "This is not implemented yet."
+ if simplifyEmail(message['from']).lower() in getRemailerConfig('blockedaddresses'):
+ logging.debug("Skipping the remailer-stats request because sender is in the blocked addresses..." + messageId)
+ else:
+ mail = MailResponse(To = simplifyEmail(message['from']),
+ From = getRemailerConfig('remailernobodyaddress'),
+ Subject = "Statistics for the " + getRemailerConfig('remailershortname') + " remailer",
+ Body = stats)
+ relay.deliver(mail.to_message())
+ elif subject == 'remailer-conf':
+ logging.debug("Processing a remailer-conf request..." + messageId)
+ conf = "This is not implemented yet."
+ if simplifyEmail(message['from']).lower() in getRemailerConfig('blockedaddresses'):
+ logging.debug("Skipping the remailer-conf request because sender is in the blocked addresses..." + messageId)
+ else:
+ mail = MailResponse(To = simplifyEmail(message['from']),
+ From = getRemailerConfig('remailernobodyaddress'),
+ Subject = "Capabilities of the " + getRemailerConfig('remailershortname') + " remailer",
+ Body = conf)
+ relay.deliver(mail.to_message())
+ elif subject == 'remailer-adminkey':
+ logging.debug("Processing a remailer-adminkey request..." + messageId)
+ if simplifyEmail(message['from']).lower() in getRemailerConfig('blockedaddresses'):
+ logging.debug("Skipping the remailer-adminkey request because sender is in the blocked addresses..." + messageId)
+ else:
+ adminkey = view.respond(
+ getRemailerConfig(),
+ 'adminkey.msg',
+ From=getRemailerConfig('remailernobodyaddress'),
+ To=simplifyEmail(message['from']),
+ Subject='Admin Contact Key')
+ relay.deliver(adminkey)
elif subject == 'remailer-help':
- logging.debug("Processing a remailer-help request...")
- help = view.respond(
- getRemailerConfig({'senderaddress' : simplifyEmail(message['from'])}),
- 'help.msg',
- From=getRemailerConfig('remailernobodyaddress'),
- To=message['from'],
- Subject='Remailer Help')
- relay.deliver(help)
- pass
+ logging.debug("Processing a remailer-help request..." + messageId)
+ if simplifyEmail(message['from']).lower() in getRemailerConfig('blockedaddresses'):
+ logging.debug("Skipping the remailer-help request because sender is in the blocked addresses..." + messageId)
+ else:
+ help = view.respond(
+ getRemailerConfig({'senderaddress' : simplifyEmail(message['from'])}),
+ 'help.msg',
+ From=getRemailerConfig('remailernobodyaddress'),
+ To=simplifyEmail(message['from']),
+ Subject='Remailer Help')
+ relay.deliver(help)
elif subject == 'remailer-key' or subject == 'remailer-keys':
- logging.debug("Processing a remailer-key request...")
-
- privkeys = getKeyStore().listPrivateKeys()
- if len(privkeys) > 1:
- raise Exception("More than one private key found in the keystore...")
- mixKey = getKeyStore().getPublicKey(privkeys[0]).toMixFormat()
-
- mixKey = getRemailerConfig().getMixKeyHeader(privkeys[0]) + "\n\n" + mixKey
-
- keys = ""
- keys += getRemailerConfig().getCapString()
- keys += "\n\n"
- keys += mixKey
-
- mail = MailResponse(To = simplifyEmail(message['from']),
- From = getRemailerConfig('remailernobodyaddress'),
- Subject = "Remailer key for " + getRemailerConfig('remailershortname'),
- Body = keys)
- relay.deliver(mail.to_message())
+ logging.debug("Processing a remailer-key request..." + messageId)
+ if simplifyEmail(message['from']).lower() in getRemailerConfig('blockedaddresses'):
+ logging.debug("Skipping the remailer-key request because sender is in the blocked addresses..." + messageId)
+ else:
+ privkeys = getKeyStore().listPrivateKeys()
+ if len(privkeys) > 1:
+ raise Exception("More than one private key found in the keystore...")
+ mixKey = getKeyStore().getPublicKey(privkeys[0]).toMixFormat()
+
+ mixKey = getRemailerConfig().getMixKeyHeader(privkeys[0]) + "\n\n" + mixKey
+
+ keys = ""
+ keys += getRemailerConfig().getCapString()
+ keys += "\n\n"
+ keys += mixKey
+
+ mail = MailResponse(To = simplifyEmail(message['from']),
+ From = getRemailerConfig('remailernobodyaddress'),
+ Subject = "Remailer key for " + getRemailerConfig('remailershortname'),
+ Body = keys)
+ relay.deliver(mail.to_message())
else:
- logging.debug("Processing a Message...")
+ logging.debug("Processing a Message..." + messageId)
body = body.strip()
if body.startswith('destination-block'):
- logging.debug("Processing a destination-block message...")
- pass
+ logging.debug("Processing a destination-block message..." + messageId)
+
+ bodylines = body.split("\n")
+ blockaddress = bodylines[0].replace("destination-block ", "").lower().strip()
+ logging.debug("Processing a destination-block request for " + blockaddress)
+
+ getRemailerConfig('blockedaddresses').append(blockaddress)
+
+ f = open(getRemailerConfig('filelocations')['blockedaddresses'], 'a')
+ f.write(blockaddress + "\n")
+ f.close()
elif body.startswith('::'):
- logging.debug("Processing a Mix Message...")
+ logging.debug("Processing a Mix Message..." + messageId)
mixmsg = MixMessage(body)
#This is where it _should_ go into the pool, but won't for now...
@@ -103,26 +147,29 @@ def REMAIL(message, to=None, suffix=None, host=None):
Subject = mixmsg.deliverySubject(),
Body = mixmsg.deliveryBody())
relay.deliver(mail.to_message())
- logging.debug("Delivering an Intermediate Hop Message...")
+ logging.debug("Delivering an Intermediate Hop Message..." + messageId)
elif mixmsg.PacketType == MixPacketType.FinalHop:
for deliveryAddr in mixmsg.deliveryTo():
- mail = MailResponse(To = deliveryAddr,
- From = getRemailerConfig('remailernobodyaddress'),
- Subject = mixmsg.deliverySubject(),
- Body = mixmsg.deliveryBody())
- for h, v in mixmsg.deliveryHeaders():
- mail[h] = v
- relay.deliver(mail.to_message())
- logging.debug("Delivering a Final Hop Message...")
+ logging.debug("Delivering a Final Hop Message..." + messageId)
+ if deliveryAddr.lower() in getRemailerConfig('blockedaddresses'):
+ logging.debug("Skipping a destination because it is in the blocked addresses..." + messageId)
+ else:
+ mail = MailResponse(To = deliveryAddr,
+ From = getRemailerConfig('remailernobodyaddress'),
+ Subject = mixmsg.deliverySubject(),
+ Body = mixmsg.deliveryBody())
+ for h, v in mixmsg.deliveryHeaders():
+ mail[h] = v
+ relay.deliver(mail.to_message())
elif mixmsg.PacketType == MixPacketType.DummyMessage:
logging.debug("Ignoring a Dummy Message...")
else:
- logging.debug("Mix Message not understood...", messageId)
+ logging.debug("Mix Message not understood..." + messageId)
elif body.startswith('-----BEGIN PGP MESSAGE-----'):
- logging.debug("Processing a PGP message...")
+ logging.debug("Processing a PGP message..." + messageId)
pass
else:
- logging.debug("Passing on a remailer message not understood...")
+ logging.debug("Passing on a remailer message not understood..." + messageId)
return REMAIL
View
@@ -35,7 +35,7 @@ def __init__(self):
self['ForbiddenHeaderValues'] = ['Authenticated sender is']
self['remailerversionname'] = "mixmaster-faster"
- self['remailerversionnum'] = "0.2.1"
+ self['remailerversionnum'] = "0.3.0"
self['remailerversion'] = self['remailerversionname'] + self['remailerversionnum']
self['remailerkeypassword'] = 'FILL_IN_REMAILER_PASSPHRASE'
@@ -47,12 +47,37 @@ def __init__(self):
self['remaileradminaddress'] = 'FILL_IN_REMAILER_ADMIN_ADDRESS'
self['remailerabuseaddress'] = 'FILL_IN_REMAILER_ABUSE_ADDRESS'
+ self['adminpublickey'] = ''
+ self['blockedaddresses'] = []
+
+ self['statsdirectory'] = 'FILL_IN_STATS_LOCATION'
+
self['filelocations'] = {}
+ self['filelocations']['adminpublickey'] = 'app/data/adminpublickey.asc'
+ self['filelocations']['blockedaddresses'] = 'app/data/blockedaddresses.txt'
self['filelocations']['mlist'] = 'app/data/mlist.txt'
self['filelocations']['rlist'] = 'app/data/rlist.txt'
self['filelocations']['pubring.mix'] = 'app/data/pubring.mix'
self['filelocations']['pgp-all.asc'] = 'app/data/pgp-all.asc'
self['filelocations']['secring.mix'] = 'app/data/secring.mix'
+
+ # ======================================================================
+
+ try:
+ f = open(self['filelocations']['adminpublickey'], 'r')
+ except IOError:
+ f = open('../../' + self['filelocations']['adminpublickey'], 'r')
+ adminpublickeylines = f.readlines()
+ f.close()
+ self['adminpublickey'] = "".join(adminpublickeylines)
+
+ try:
+ f = open(self['filelocations']['blockedaddresses'], 'r')
+ except IOError:
+ f = open('../../' + self['filelocations']['blockedaddresses'], 'r')
+ for l in f:
+ self['blockedaddresses'].append(l.lower().strip())
+ f.close()
def allowHeader(self, h, v):
for f in self['ForbiddenHeaders']:
View
@@ -1,5 +1,6 @@
#!/usr/bin/python
+import subprocess
import logging, logging.config
from mixKey import *
@@ -9,33 +10,51 @@
def getKeyStore():
global _mixKeyStore
if not _mixKeyStore:
- _mixKeyStore = MixKeyStore()
+ _mixKeyStore = loadFreshKeystore()
- try:
- f = open(getRemailerConfig()['filelocations']['secring.mix'], 'r')
- except IOError:
- f = open('../../' + getRemailerConfig()['filelocations']['secring.mix'], 'r')
- privateKeyLines = f.readlines()
- f.close()
- _mixKeyStore.addKey(privateKeyLines, getRemailerConfig('remailerkeypassword'))
-
- try:
- f = open(getRemailerConfig()['filelocations']['pubring.mix'], 'r')
- except IOError:
- f = open('../../' + getRemailerConfig()['filelocations']['pubring.mix'], 'r')
- lines = f.readlines()
- f.close()
- key = []
- for l in lines:
- l = l.strip()
- if l == "-----End Mix Key-----":
- key.append(l)
- _mixKeyStore.addKey(key)
- key = []
- else:
- key.append(l)
+ return _mixKeyStore
+
+def loadFreshKeystore():
+ _mixKeyStore = MixKeyStore()
+ # This assumes only one private key will be found in the file.
+ try:
+ f = open(getRemailerConfig()['filelocations']['secring.mix'], 'r')
+ except IOError:
+ f = open('../../' + getRemailerConfig()['filelocations']['secring.mix'], 'r')
+ privateKeyLines = f.readlines()
+ f.close()
+ _mixKeyStore.addKey(privateKeyLines, getRemailerConfig('remailerkeypassword'))
+
+ try:
+ f = open(getRemailerConfig()['filelocations']['pubring.mix'], 'r')
+ except IOError:
+ f = open('../../' + getRemailerConfig()['filelocations']['pubring.mix'], 'r')
+ lines = f.readlines()
+ f.close()
+ key = []
+ for l in lines:
+ l = l.strip()
+ if l == "-----End Mix Key-----":
+ key.append(l)
+ _mixKeyStore.addKey(key)
+ key = []
+ else:
+ key.append(l)
return _mixKeyStore
+
+def refreshStats():
+ devnull = open("/dev/null", "w")
+ subprocess.call(["wget", getRemailerConfig('statsdirectory') + "mlist.txt"], stderr=devnull)
+ subprocess.call(["wget", getRemailerConfig('statsdirectory') + "rlist.txt"], stderr=devnull)
+ subprocess.call(["wget", getRemailerConfig('statsdirectory') + "pubring.mix"], stderr=devnull)
+ subprocess.call(["wget", getRemailerConfig('statsdirectory') + "pgp-all.asc"], stderr=devnull)
+ subprocess.call(["mv", "mlist.txt", "rlist.txt", "pubring.mix", "pgp-all.asc", "app/data/"])
+ devnull.close()
+
+def refreshKeyStore():
+ global _mixKeyStore
+ _mixKeyStore = loadFreshKeystore()
class MixKeyStore:
keystore = {}
Oops, something went wrong.

0 comments on commit eb4024e

Please sign in to comment.