[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[minion-cvs] Refactor incoming queues for better separation of permi...
Update of /home/minion/cvsroot/src/minion/lib/mixminion/server
In directory moria.mit.edu:/tmp/cvs-serv8806/lib/mixminion/server
Modified Files:
ServerKeys.py ServerMain.py
Log Message:
Refactor incoming queues for better separation of permissions; add publication
Index: ServerKeys.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerKeys.py,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- ServerKeys.py 23 May 2003 07:54:12 -0000 1.22
+++ ServerKeys.py 23 May 2003 22:49:30 -0000 1.23
@@ -12,9 +12,12 @@
import os
import socket
+import re
import sys
import time
import threading
+import urllib
+import urllib2
import mixminion._minionlib
import mixminion.Crypto
@@ -27,7 +30,7 @@
signServerInfo
from mixminion.Common import AtomicFile, LOG, MixError, MixFatalError, \
- createPrivateDir, \
+ ceilDiv, createPrivateDir, \
checkPrivateFile, formatBase64, formatDate, formatTime, previousMidnight,\
secureDelete
@@ -44,6 +47,12 @@
#FFFF Make this configurable? (Set to 2 weeks).
PREPUBLICATION_INTERVAL = 14*24*60*60
+# DOCDOC
+#
+#FFFF Make this configurable
+#DIRECTORY_UPLOAD_URL = "http://mixminion.net/cgi-bin/publish"
+DIRECTORY_UPLOAD_URL = "http://192.168.0.1/cgi-bin/publish"
+
#----------------------------------------------------------------------
class ServerKeyring:
"""A ServerKeyring remembers current and future keys, descriptors, and
@@ -99,6 +108,7 @@
self.hashDir = os.path.join(self.homeDir, 'work', 'hashlogs')
self.keyOverlap = config['Server']['PublicKeyOverlap'].getSeconds()
self.nextUpdate = None
+ self.currentKeys = None
self.checkKeys()
def checkKeys(self):
@@ -113,8 +123,6 @@
if not os.path.exists(self.keyDir):
LOG.info("Creating server keystore at %s", self.keyDir)
createPrivateDir(self.keyDir)
-
- unpublished = []
# Iterate over the entires in HOME/keys
for dirname in os.listdir(self.keyDir):
@@ -145,11 +153,6 @@
LOG.debug("Found key %s (valid from %s to %s)",
dirname, formatDate(t1), formatDate(t2))
- if not keyset.isPublished():
- unpublished.append(keysetname)
-
- self.unpublished = unpublished
-
# Now, sort the key intervals by starting time.
self.keySets.sort()
self.keyRange = (firstKey, lastKey)
@@ -188,6 +191,35 @@
return key
+ def publishKeys(self, allKeys=0):
+ """DOCDOC"""
+ keySets = [ ks for _, _, ks in self.keySets ]
+ if allKeys:
+ LOG.info("Republishing all known keys to directory server")
+ else:
+ keySets = [ ks for ks in keySets if not ks.isPublished() ]
+ if not keySets:
+ LOG.debug("publishKeys: no unpublished keys found")
+ return
+ LOG.info("Publishing %s keys to directory server...",len(keySets))
+
+ rejected = 0
+ for ks in keySets:
+ status = ks.publish(DIRECTORY_UPLOAD_URL)
+ if status == 'error':
+ LOG.info("Error publishing a key; giving up")
+ return 0
+ elif status == 'reject':
+ rejected += 1
+ else:
+ assert status == 'accept'
+ if rejected == 0:
+ LOG.info("All keys published successfully.")
+ return 1
+ else:
+ LOG.info("%s/%s keys were rejected." , rejected, len(keySets))
+ return 0
+
def removeIdentityKey(self):
"""Remove this server's identity key."""
fn = os.path.join(self.keyDir, "identity.key")
@@ -212,10 +244,17 @@
if self.getNextKeygen() > now-10: # 10 seconds of leeway
return
- lastExpiry = self.keySets[-1][1]
+ if self.keySets:
+ lastExpiry = self.keySets[-1][1]
+ else:
+ lastExpiry = now
+
+ timeToCover = lastExpiry + PREPUBLICATION_INTERVAL - now
+
lifetime = self.config['Server']['PublicKeyLifetime'].getSeconds()
- nKeys = ceilDiv(PREPUBLICATION_INTERVAL, lifetime)
+ nKeys = ceilDiv(timeToCover, lifetime)
+ LOG.debug("Creating %s keys", nKeys)
self.createKeys(num=nKeys)
def createKeys(self, num=1, startAt=None):
@@ -277,8 +316,10 @@
# PREPUBLICATION_INTERVAL seconds after that, and we assume that
# a key takes up to PUBLICATION_LATENCY seconds to make it into the
# directory.
- nextKeygen = lastExpiry - PUBLICATION_LATENCY - PREPUBLICATION_INTERVAL
+ nextKeygen = lastExpiry - PUBLICATION_LATENCY
+ LOG.info("Last expiry at %s; next keygen at %s",
+ formatTime(lastExpiry,1), formatTime(nextKeygen, 1))
return nextKeygen
def removeDeadKeys(self, now=None):
@@ -326,13 +367,13 @@
return [ (va,vu,k) for (va,vu,k) in self.keySets
if va < now and vu > cutoff ]
- def getServerKeysets(self):
+ def getServerKeysets(self, now=None):
"""Return a ServerKeyset object for the currently live key.
DOCDOC"""
# FFFF Support passwords on keys
keysets = [ ]
- for va, vu, ks in self._getLiveKeys():
+ for va, vu, ks in self._getLiveKeys(now):
ks.load()
keysets.append(ks)
@@ -382,7 +423,7 @@
packetKeys.append(k.getPacketKey())
hashLogs.append(mixminion.server.HashLog.HashLog(
k.getHashLogFileName(), k.getPacketKeyID()))
- packetHandler.setKeys(packetkeys, hashLogs)
+ packetHandler.setKeys(packetKeys, hashLogs)
self.nextUpdate = None
self.getNextKeyRotation(keys)
@@ -512,13 +553,19 @@
return self.published
def markAsPublished(self):
"""DOCDOC"""
- f = open(self.published, 'w')
+ f = open(self.publishedFile, 'w')
try:
f.write(formatTime(time.time(), 1))
f.write("\n")
finally:
f.close()
self.published = 1
+ def markAsUnpublished(self):
+ try:
+ os.unlink(self.publishedFile)
+ except OSError:
+ pass
+ self.published = 0
def regenerateServerDescriptor(self, config, identityKey, validAt=None):
"""DOCDOC"""
self.load()
@@ -532,6 +579,49 @@
self.keyroot, self.keyname, self.hashroot,
validAt=validAt, useServerKeys=1)
self.serverinfo = self.validAfter = self.validUntil = None
+
+ def publish(self, url):
+ """ Returns 'accept', 'reject', 'error'. """
+ fname = self.getDescriptorFileName()
+ f = open(fname, 'r')
+ try:
+ descriptor = f.read()
+ finally:
+ f.close()
+ fields = urllib.urlencode({"desc" : descriptor})
+ try:
+ try:
+ f = urllib2.urlopen(url, fields)
+ info = f.info()
+ reply = f.read()
+ except:
+ LOG.error_exc(sys.exc_info(),
+ "Error publishing server descriptor")
+ return 'error'
+ finally:
+ f.close()
+
+ if info.get('Content-Type') != 'text/plain':
+ LOG.error("Bad content type %s from directory"%info.get(
+ 'Content-Type'))
+ return 'error'
+ m = DIRECTORY_RESPONSE_RE.search(reply)
+ if not m:
+ LOG.error("Didn't understand reply from directory: %r",
+ reply[:100])
+ return 'error'
+ ok = int(m.group(1))
+ msg = m.group(2)
+ if not ok:
+ LOG.error("Directory rejected descriptor: %r", msg)
+ return 'reject'
+
+ LOG.info("Directory accepted descriptor: %r", msg)
+ self.markAsPublished()
+ return 'accept'
+
+DIRECTORY_RESPONSE_RE = re.compile(r'^Status: (0|1)[ \t]*\nMessage: (.*)$',
+ re.M)
class _WarnWrapper:
"""Helper for 'checkDescriptorConsistency' to keep its implementation
Index: ServerMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerMain.py,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- ServerMain.py 23 May 2003 07:54:12 -0000 1.53
+++ ServerMain.py 23 May 2003 22:49:30 -0000 1.54
@@ -539,6 +539,7 @@
#XXXX004 Check whether config matches serverinfo
self.keyring = mixminion.server.ServerKeys.ServerKeyring(config)
self.keyring.createKeysAsNeeded()
+ self.keyring.publishKeys()
LOG.debug("Initializing packet handler")
self.packetHandler = mixminion.server.PacketHandler.PacketHandler()
@@ -606,7 +607,7 @@
" updateKeys delaying for 2 minutes")
# This will cause getNextKeyRotation to return 2 minutes later
# than now.
- self.keyring.nextUpdate = time.time() += 120
+ self.keyring.nextUpdate = time.time() + 120
return
try:
@@ -619,7 +620,8 @@
def c(self=self):
self.keyring.lock()
try:
- self.keyring.createKeysAsNeeded
+ self.keyring.createKeysAsNeeded()
+ self.keyring.publishKeys()
finally:
self.keyring.unlock()
self.processingThread.addJob(c)
@@ -651,13 +653,13 @@
self.mmtpServer.getNextTimeoutTime)
self.scheduleRecurringComplex(self.keyring.getNextKeyRotation(),
- self.updateKeys,
"KEY_ROTATE",
+ self.updateKeys,
self.keyring.getNextKeyRotation)
self.scheduleRecurringComplex(self.keyring.getNextKeygen(),
- self.generateKeys,
"KEY_GEN",
+ self.generateKeys,
self.keyring.getNextKeygen)
nextMix = self.mixPool.getNextMixTime(now)