[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[minion-cvs] Mixminion just delivered its first test message. Still...
Update of /home/minion/cvsroot/src/minion/lib/mixminion
In directory moria.seul.org:/tmp/cvs-serv13014/lib/mixminion
Modified Files:
BuildMessage.py Common.py Config.py HashLog.py MMTPServer.py
Main.py Modules.py PacketHandler.py ServerMain.py test.py
testSupport.py
Added Files:
ClientMain.py
Log Message:
Mixminion just delivered its first test message. Still requires babysitting
that only I can do, though. :P BTW, happy birthday to me!
BuildMessage.py: Add warning in comment
Common.py: Withstand logging in nonexistant dir
Config.py:
- Path len is an int
- Add more validation
HashLog.py:
- Withstand logging in nonexistant dir.
MMTPServer.py:
- Quiet debugging a bit
- Debug server class
Main.py:
- Add client CLI
ClientMain.py:
- Stub client CLI. Doesn't do anything worthwhile yet
Modules.py:
- Fix dumb typo
ServerMain.py:
- Much debugging
test.py:
- Suspend log more consistently
testSupport.py:
- Debug testing module
--- NEW FILE: ClientMain.py ---
# Copyright 2002 Nick Mathewson. See LICENSE for licensing information.
# $Id: ClientMain.py,v 1.1 2002/08/31 04:12:36 nickm Exp $
"""mixminion.ClientMain
Code for Mixminion command-line client.
XXXX THIS ISN'T IMPLEMENTED YET! This file is just a placeholder that
XXXX routes a testing message through a few servers so I can make sure that
XXXX at least one configuration works.
"""
import os
import getopt
import sys
import time
import bisect
import mixminion.Crypto
from mixminion.Common import getLog, floorDiv
import mixminion.Config
import mixminion.BuildMessage
import mixminion.MMTPClient
import mixminion.Modules
def sendTestMessage(servers1, servers2):
assert len(servers1)
assert len(servers2)
payload = """
Insert
Example
Message
Here.
"""
rt, ri = 0xFFFE, "deliver"
m = mixminion.BuildMessage.buildForwardMessage(payload,
rt, ri,
servers1, servers2)
firstHop = servers1[0]
b = mixminion.MMTPClient.BlockingClientConnection(firstHop.getAddr(),
firstHop.getPort(),
firstHop.getKeyID())
b.connect()
b.sendPacket(m)
b.shutdown()
def readConfigFile(configFile):
try:
return mixminion.Config.ClientConfig(fname=configFile)
except (IOError, OSError), e:
print >>sys.stderr, "Error reading configuration file %r:"%configFile
print >>sys.stderr, " ", str(e)
sys.exit(1)
except mixminion.Config.ConfigError, e:
print >>sys.stderr, "Error in configuration file %r"%configFile
print >>sys.stderr, str(e)
sys.exit(1)
# XXXX This isn't anything LIKE the final client interface: for now, I'm
# XXXX just testing the server.
def runClient(cmd, args):
options, args = getopt.getopt(args, "hf:", ["help", "config="])
configFile = '~/.mixminion/mixminion.conf'
usage = 0
for opt,val in options:
if opt in ('-h', '--help'):
usage=1
elif opt in ('-f', '--config'):
configFile = val
if usage:
print >>sys.stderr, "Usage: %s [-h] [-f configfile] server1 server2..."%cmd
sys.exit(1)
config = readConfigFile(os.path.expanduser(configFile))
getLog().setMinSeverity("INFO")
mixminion.Crypto.init_crypto(config)
if len(args) < 2:
print >> sys.stderr, "I need at least 2 servers"
servers = [ mixminion.ServerInfo.ServerInfo(fn) for fn in args ]
idx = floorDiv(len(servers),2)
sendTestMessage(servers[:idx], servers[idx:])
Index: BuildMessage.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/BuildMessage.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- BuildMessage.py 6 Aug 2002 16:09:21 -0000 1.11
+++ BuildMessage.py 31 Aug 2002 04:12:36 -0000 1.12
@@ -21,6 +21,9 @@
exitInfo: The routing info for the final node
path1: Sequence of ServerInfo objects for the first leg of the path
path2: Sequence of ServerInfo objects for the 2nd leg of the path
+
+ Note: If either path is empty, the message is vulnerable to tagging
+ attacks! (FFFF we should check this.)
"""
return _buildMessage(payload, exitType, exitInfo, path1, path2)
Index: Common.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Common.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Common.py 29 Aug 2002 03:30:21 -0000 1.19
+++ Common.py 31 Aug 2002 04:12:36 -0000 1.20
@@ -208,6 +208,9 @@
if self.file is not None:
self.file.close()
try:
+ parent = os.path.split(self.fname)[0]
+ if not os.path.exists(parent):
+ createPrivateDir(parent)
self.file = open(self.fname, 'a')
except OSError, e:
self.file = None
Index: Config.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Config.py,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- Config.py 29 Aug 2002 03:30:21 -0000 1.13
+++ Config.py 31 Aug 2002 04:12:36 -0000 1.14
@@ -51,7 +51,6 @@
import os
import re
import binascii
-import time
import socket # for inet_aton and error
from cStringIO import StringIO
@@ -624,15 +623,13 @@
'User' : { 'UserDir' : ('ALLOW', None, "~/.mixminion" ) },
'Security' : { 'PathLength' : ('ALLOW', _parseInt, "8"),
'SURBAddress' : ('ALLOW', None, None),
- 'SURBPathLength' : ('ALLOW', None, "8") },
+ 'SURBPathLength' : ('ALLOW', _parseInt, "8") },
}
def __init__(self, fname=None, string=None):
_ConfigFile.__init__(self, fname, string)
def validate(self, sections, entries, lines, contents):
- #XXXX Write this
- pass
-
+ _validateHostSection(sections.get('Host', {}))
SERVER_SYNTAX = {
'Host' : ClientConfig._syntax['Host'],
@@ -695,7 +692,34 @@
_ConfigFile.__init__(self, fname, string)
def validate(self, sections, entries, lines, contents):
- #XXXX write this.
+ log = getLog()
+ _validateHostSection(sections.get('Host', {}))
+ # Server section
+ server = sections['Server']
+ bits = server['IdentityKeyBits']
+ if not (2048 <= bits <= 4096):
+ raise ConfigError("IdentityKeyBits must be between 2048 and 4096")
+ if server['EncryptIdentityKey']:
+ log.warn("Identity key encryption not yet implemented")
+ if server['EncryptPrivateKey']:
+ log.warn("Encrypted private keys not yet implemented")
+ if server['PublicKeyLifetime'][2] < 24*60*60:
+ raise ConfigError("PublicKeyLifetime must be at least 1 day.")
+ if server['PublicKeySloppiness'][2] > 20*60:
+ raise ConfigError("PublicKeySloppiness must be <= 20 minutes.")
+ if [e for e in entries['Server'] if e[0]=='Mode']:
+ log.warn("Mode specification is not yet supported.")
+
+ if not sections['Incoming/MMTP'].get('Enabled'):
+ log.warn("Disabling incoming MMTP is not yet supported.")
+ if [e for e in entries['Incoming/MMTP'] if e[0] in ('Allow', 'Deny')]:
+ log.warn("Allow/deny are not yet supported")
+
+ if not sections['Outgoing/MMTP'].get('Enabled'):
+ log.warn("Disabling incoming MMTP is not yet supported.")
+ if [e for e in entries['Outgoing/MMTP'] if e[0] in ('Allow', 'Deny')]:
+ log.warn("Allow/deny are not yet supported")
+
self.moduleManager.validate(sections, entries, lines, contents)
def __loadModules(self, section, sectionEntries):
@@ -712,3 +736,8 @@
def getModuleManager(self):
"Return the module manager initialized by this server."
return self.moduleManager
+
+def _validateHostSection(sec):
+ #XXXX
+ pass
+
Index: HashLog.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/HashLog.py,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- HashLog.py 9 Jul 2002 04:07:14 -0000 1.9
+++ HashLog.py 31 Aug 2002 04:12:36 -0000 1.10
@@ -5,8 +5,9 @@
Persistant memory for the hashed secrets we've seen."""
+import os
import anydbm, dumbdbm
-from mixminion.Common import MixFatalError, getLog
+from mixminion.Common import MixFatalError, getLog, createPrivateDir
__all__ = [ 'HashLog' ]
@@ -37,6 +38,9 @@
def __init__(self, filename, keyid):
"""Create a new HashLog to store data in 'filename' for the key
'keyid'."""
+ parent = os.path.split(filename)[0]
+ createPrivateDir(parent)
+ print filename
self.log = anydbm.open(filename, 'c')
if isinstance(self.log, dumbdbm._Database):
getLog().warn("Warning: logging packet digests to a flat file.")
Index: MMTPServer.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/MMTPServer.py,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- MMTPServer.py 29 Aug 2002 03:30:21 -0000 1.15
+++ MMTPServer.py 31 Aug 2002 04:12:36 -0000 1.16
@@ -63,8 +63,8 @@
If we receive an unblocked signal, return immediately.
"""
- trace("%s readers, %s writers" % (len(self.readers),
- len(self.writers)))
+## trace("%s readers, %s writers" % (len(self.readers),
+## len(self.writers)))
readfds = self.readers.keys()
writefds = self.writers.keys()
@@ -570,7 +570,8 @@
msg = self.messageList[0]
self.expectedDigest = sha1(msg+"RECEIVED")
msg = SEND_CONTROL+msg+sha1(msg+"SEND")
-
+ assert len(msg) == SEND_RECORD_LEN
+
self.beginWrite(msg)
self.finished = self.__sentMessage
@@ -641,14 +642,21 @@
sock.setblocking(0)
con = MMTPServerConnection(sock, tls, self.onMessageReceived)
con.register(self)
+ return con
def stopListening(self):
self.listener.shutdown()
def sendMessages(self, ip, port, keyID, messages, handles):
"""Send a set of messages to a given server."""
- con = MMTPClientConnection(ip, port, keyID, messages, handles,
- self.onMessageSent)
+ #XXXX for debugging
+ for m,h in zip(messages, handles):
+ assert len(m) == MESSAGE_LEN
+ assert len(h) < 32
+
+ con = MMTPClientConnection(self.context,
+ ip, port, keyID, messages, handles,
+ self.onMessageSent, self.onMessageUndeliverable)
con.register(self)
def onMessageReceived(self, msg):
Index: Main.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Main.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Main.py 29 Aug 2002 03:30:21 -0000 1.3
+++ Main.py 31 Aug 2002 04:12:36 -0000 1.4
@@ -75,6 +75,7 @@
_COMMANDS = {
"unittests" : ( 'mixminion.test', 'testAll' ),
"benchmarks" : ( 'mixminion.benchmark', 'timeAll' ),
+ "client" : ( 'mixminion.ClientMain', 'runClient' ),
"server" : ( 'mixminion.ServerMain', 'runServer' ),
"server-keygen" : ( 'mixminion.ServerMain', 'runKeygen')
}
Index: Modules.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Modules.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Modules.py 29 Aug 2002 03:30:21 -0000 1.10
+++ Modules.py 31 Aug 2002 04:12:36 -0000 1.11
@@ -108,7 +108,7 @@
def queueMessage(self, (exitType, exitInfo), message):
try:
- res = self.module.processMessage(exitType, exitInfo, message)
+ res = self.module.processMessage(message, exitType, exitInfo)
if res == DELIVER_OK:
return
elif res == DELIVER_FAIL_RETRY:
Index: PacketHandler.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/PacketHandler.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- PacketHandler.py 19 Aug 2002 20:27:02 -0000 1.6
+++ PacketHandler.py 31 Aug 2002 04:12:36 -0000 1.7
@@ -38,6 +38,7 @@
self.privatekey = privatekey
self.hashlog = hashlog
except:
+ # XXXX Don't do except:; name an exception.
self.privatekey = (privatekey, )
self.hashlog = (hashlog, )
Index: ServerMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/ServerMain.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- ServerMain.py 29 Aug 2002 03:30:21 -0000 1.7
+++ ServerMain.py 31 Aug 2002 04:12:36 -0000 1.8
@@ -175,7 +175,7 @@
nextStart = startAt + self.config['Server']['PublicKeyLifetime'][2]
- getLog().info("Generating key %s to run from %s through %s",
+ getLog().info("Generating key %s to run from %s through %s (GMT)",
keyname, _date(startAt), _date(nextStart-3600))
generateServerDescriptorAndKeys(config=self.config,
identityKey=self.getIdentityKey(),
@@ -210,7 +210,6 @@
self.nextKeyRotation = 0
return None
-
w = when
if when is None:
when = time.time()
@@ -260,8 +259,11 @@
def getPacketHandler(self):
"""Create and return a PacketHandler from the currently live key."""
keys = self.getServerKeyset()
- return mixminion.PacketHandler.PacketHandler(keys.getPacketKey(),
- keys.getHashLogFileName())
+ packetKey = keys.getPacketKey()
+ hashlog = mixminion.HashLog.HashLog(keys.getHashLogFileName(),
+ keys.getMMTPKeyID())
+ return mixminion.PacketHandler.PacketHandler(packetKey,
+ hashlog)
class IncomingQueue(mixminion.Queue.DeliveryQueue):
"""A DeliveryQueue to accept messages from incoming MMTP connections,
@@ -280,14 +282,14 @@
def queueMessage(self, msg):
"""Add a message for delivery"""
- mixminion.DeliveryQueue.queueMessage(None, msg)
+ mixminion.Queue.DeliveryQueue.queueMessage(self, None, msg)
def deliverMessages(self, msgList):
"Implementation of abstract method from DeliveryQueue."
ph = self.packetHandler
for handle, _, message, n_retries in msgList:
try:
- res = ph.packetHandler(message)
+ res = ph.processMessage(message)
if res is None:
# Drop padding before it gets to the mix.
getLog().info("Padding message dropped")
@@ -315,7 +317,7 @@
def queueObject(self, obj):
"""Insert an object into the queue."""
- self.queue.queueObject(ob)
+ self.queue.queueObject(obj)
def connectQueues(self, outgoing, manager):
"""Sets the queue for outgoing mixminion packets, and the
@@ -327,15 +329,17 @@
"""Get a batch of messages, and queue them for delivery as
appropriate."""
handles = self.queue.getBatch()
+ getLog().trace("Mixing %s messages", len(handles))
for h in handles:
tp, info = self.queue.getObject(h)
if tp == 'EXIT':
rt, ri, app_key, payload = info
- self.moduleManager.queueMessage((rt, ri), payload)
+ self.moduleManager.queueMessage(payload, rt, ri)
else:
assert tp == 'QUEUE'
ipv4, msg = info
self.outgoingQueue.queueMessage(ipv4, msg)
+ self.queue.removeMessage(h)
class OutgoingQueue(mixminion.Queue.DeliveryQueue):
"""DeliveryQueue to send messages via outgoing MMTP connections."""
@@ -357,9 +361,9 @@
for handle, addr, message, n_retries in msgList:
msgs.setdefault(addr, []).append( (handle, message) )
for addr, messages in msgs.items():
- messages, handles = zip(*messages)
+ handles, messages = zip(*messages)
self.server.sendMessages(addr.ip, addr.port, addr.keyinfo,
- messages, handles)
+ list(messages), list(handles))
class _MMTPServer(mixminion.MMTPServer.MMTPServer):
"""Implementation of mixminion.MMTPServer that knows about
@@ -462,7 +466,7 @@
options, args = getopt.getopt(args, "hf:", ["help", "config="])
if args:
usageAndExit(cmd)
- configFile = "/etc/miniond.conf"
+ configFile = "/etc/mixminiond.conf"
for o,v in options:
if o in ('-h', '--help'):
usageAndExit()
@@ -507,6 +511,7 @@
getLog().fatal_exc(sys.exc_info(),"Exception while running server")
getLog().info("Server shutting down")
+
sys.exit(0)
#----------------------------------------------------------------------
@@ -539,5 +544,4 @@
for i in xrange(keys):
keyring.createKeys(1)
print >> sys.stderr, ".... (%s/%s done)" % (i+1,keys)
-
Index: test.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/test.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- test.py 29 Aug 2002 03:30:21 -0000 1.25
+++ test.py 31 Aug 2002 04:12:36 -0000 1.26
@@ -2135,7 +2135,11 @@
def testServerInfoGen(self):
identity = _getIdentityKey()
d = mix_mktemp()
- conf = mixminion.Config.ServerConfig(string=SERVER_CONFIG)
+ try:
+ suspendLog()
+ conf = mixminion.Config.ServerConfig(string=SERVER_CONFIG)
+ finally:
+ resumeLog()
if not os.path.exists(d):
os.mkdir(d, 0700)
@@ -2195,7 +2199,11 @@
identityPK))
# Now with a shorter configuration
- conf = mixminion.Config.ServerConfig(string=SERVER_CONFIG_SHORT)
+ try:
+ suspendLog()
+ conf = mixminion.Config.ServerConfig(string=SERVER_CONFIG_SHORT)
+ finally:
+ resumeLog()
mixminion.ServerInfo.generateServerDescriptorAndKeys(conf,
identity,
d,
@@ -2285,7 +2293,11 @@
Foo: 99
""" % (home_dir, mod_dir)
- conf = mixminion.Config.ServerConfig(string=cfg_test)
+ try:
+ suspendLog()
+ conf = mixminion.Config.ServerConfig(string=cfg_test)
+ finally:
+ resumeLog()
manager = conf.getModuleManager()
exampleMod = None
for m in manager.modules:
@@ -2295,7 +2307,11 @@
manager.configure(conf)
self.assertEquals(99, exampleMod.foo)
- conf = mixminion.Config.ServerConfig(string=cfg_test)
+ try:
+ suspendLog()
+ conf = mixminion.Config.ServerConfig(string=cfg_test)
+ finally:
+ resumeLog()
manager = conf.getModuleManager()
exampleMod = None
for m in manager.modules:
@@ -2348,7 +2364,11 @@
Module ExampleMod.TestModule
""" % (home_dir, mod_dir)
- conf = mixminion.Config.ServerConfig(string=cfg_test)
+ try:
+ suspendLog()
+ conf = mixminion.Config.ServerConfig(string=cfg_test)
+ finally:
+ resumeLog()
manager = conf.getModuleManager()
exampleMod = None
for m in manager.modules:
@@ -2390,7 +2410,11 @@
if _FAKE_HOME is None:
_FAKE_HOME = mix_mktemp()
cfg = SERVERCFG % { 'home' : _FAKE_HOME }
- conf = mixminion.Config.ServerConfig(string=cfg)
+ try:
+ suspendLog()
+ conf = mixminion.Config.ServerConfig(string=cfg)
+ finally:
+ resumeLog()
return mixminion.ServerMain.ServerKeyring(conf)
_IDENTITY_KEY = None
Index: testSupport.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/testSupport.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- testSupport.py 29 Aug 2002 03:30:21 -0000 1.3
+++ testSupport.py 31 Aug 2002 04:12:36 -0000 1.4
@@ -42,7 +42,7 @@
if not self.loc:
return
self.useQueue = config['Testing/DirectoryDump']['UseQueue']
- #manager.registerModule(self)
+ manager.enableModule(self)
if not os.path.exists(self.loc):
createPrivateDir(self.loc)
@@ -75,7 +75,7 @@
elif exitInfo == 'FAIL!':
return DELIVER_FAIL_NORETRY
- f = open(os.path.join(self.loc, self.next), 'w')
+ f = open(os.path.join(self.loc, str(self.next)), 'w')
self.next += 1
f.write(exitInfo)
f.write("\n")