[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[minion-cvs] Check server descriptors against configuration files, r...



Update of /home/minion/cvsroot/src/minion/lib/mixminion/server
In directory moria.mit.edu:/tmp/cvs-serv11789/lib/mixminion/server

Modified Files:
	ServerKeys.py ServerMain.py 
Log Message:
Check server descriptors against configuration files, regenerate as needed.

Avoid potentially confusing messages about 'published' descriptors that 
aren't really published.

Catch ConfigError from unrecognized descriptor versions and suggest
'server-upgrade'.



Index: ServerKeys.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerKeys.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- ServerKeys.py	23 May 2003 22:49:30 -0000	1.23
+++ ServerKeys.py	27 May 2003 17:24:49 -0000	1.24
@@ -74,27 +74,6 @@
     #
     #DOCDOC currentKeys
 
-    ## Directory layout:
-    #    MINION_HOME/work/queues/incoming/ [Queue of received,unprocessed pkts]
-    #                             mix/ [Mix pool]
-    #                             outgoing/ [Messages for mmtp delivery]
-    #                             deliver/mbox/ []
-    #                      tls/dhparam [Diffie-Hellman parameters]
-    #                      hashlogs/hash_1*  [HashLogs of packet hashes
-    #                               hash_2*    corresponding to key sets]
-    #                                ...
-    #                 log [Messages from the server]
-    #                 keys/identity.key [Long-lived identity PK]
-    #                      key_1/ServerDesc [Server descriptor]
-    #                            mix.key [packet key]
-    #                            mmtp.key [mmtp key]
-    #                            mmtp.cert [mmmtp key x509 cert]
-    #                      key_2/...
-    #                 conf/miniond.conf [configuration file]
-    #                       ....
-
-    # FFFF Support to put keys/queues in separate directories.
-
     def __init__(self, config):
         "Create a ServerKeyring from a config object"
         self._lock = threading.RLock()
@@ -169,6 +148,29 @@
                 LOG.warn("Gap in key schedule: no key from %s to %s",
                               formatDate(end), formatDate(start))
 
+    def checkDescriptorConsistency(self, regen=1):
+        """DOCDOC"""
+        identity = None
+        config = None
+        bad = []
+        for ks,_,_ in self.keySets:
+            ok = ks.checkConsistency(self.config, 0)
+            if not ok:
+                bad.append(ks)
+        if not bad:
+            return
+        
+        LOG.error("Some generated keysets do not match "
+                  "current configuration...")
+        for ks in bad:
+            va,vu = ks.getLiveness()
+            LOG.error("Keyset %s (%s--%s):",ks.keyname,formatTime(va,1),
+                      formatTime(vu,1))
+            ks.checkConsistency(self.config, 1)
+            if regen:
+                if not identity: identity = self.getIdentityKey()
+                ks.regenerateServerDescriptor(self.config, identity)
+
     def getIdentityKey(self):
         """Return this server's identity key.  Generate one if it doesn't
            exist."""
@@ -302,6 +304,13 @@
 
         self.checkKeys()
 
+    def regenerateDescriptors(self):
+        """DOCDOC"""
+        LOG.info("Regenerating server descriptors; keeping old keys.")
+        identityKey = self.getIdentityKey()
+        for ks,_,_ in self.keySets:
+            ks.regenerateServerDescriptor(self.config, identityKey)
+
     def getNextKeygen(self):
         """DOCDOC
 
@@ -566,22 +575,30 @@
         except OSError:
             pass
         self.published = 0
-    def regenerateServerDescriptor(self, config, identityKey, validAt=None):
+    def regenerateServerDescriptor(self, config, identityKey):
         """DOCDOC"""
         self.load()
-        if validAt is None:
-            validAt = self.getLiveness()[0]
+        validAt,validUntil = self.getLiveness()
         try:
             os.unlink(self.publishedFile)
         except OSError:
             pass
+        LOG.info("Regenerating descriptor for keyset %s (%s--%s)",
+                 self.keyname, formatTime(validAt,1),
+                 formatTime(validUntil,1))
         generateServerDescriptorAndKeys(config, identityKey,
                          self.keyroot, self.keyname, self.hashroot,
-                         validAt=validAt, useServerKeys=1)
+                         validAt=validAt, validUntil=validUntil,
+                         useServerKeys=1)
         self.serverinfo = self.validAfter = self.validUntil = None
+        self.markAsUnpublished()
+
+    def checkConsistency(self, config, log=1):
+        """DOCDOC"""
+        return checkDecsriptorConsistency(config,log,self.published)
 
     def publish(self, url):
-        """ Returns 'accept', 'reject', 'error'. """
+        """DOCDOC Returns 'accept', 'reject', 'error'. """
         fname = self.getDescriptorFileName()
         f = open(fname, 'r')
         try:
@@ -627,26 +644,28 @@
     """Helper for 'checkDescriptorConsistency' to keep its implementation
        short.  Counts the number of times it's invoked, and delegates to
        LOG.warn if silence is false."""
-    def __init__(self, silence):
+    def __init__(self, silence, isPublished):
         self.silence = silence
         self.called = 0
+        self.published = isPublished
     def __call__(self, *args):
         self.called += 1
+        if not self.published:
+            args = args[:]
+            args[0] = args[0].replace("published", "in unpublished descriptor")
         if not self.silence:
             LOG.warn(*args)
 
-def checkDescriptorConsistency(info, config, log=1):
+def checkDescriptorConsistency(info, config, log=1, isPublished=1):
     """Given a ServerInfo and a ServerConfig, compare them for consistency.
 
        Return true iff info may have come from 'config'.  If 'log' is
        true, warn as well.  Does not check keys.
     """
 
-    if log:
-        warn = _WarnWrapper(0)
-    else:
-        warn = _WarnWrapper(1)
+    warn = _WarnWrapper(silence = not log, isPublished=isPublished)
 
+    fixable = 1
     config_s = config['Server']
     info_s = info['Server']
     if config_s['Nickname'] and (info_s['Nickname'] != config_s['Nickname']):
@@ -658,6 +677,8 @@
     if idBits != confIDBits:
         warn("Mismatched identity bits: %s in configuration; %s published.",
              confIDBits, idBits)
+        warn.called -= 1
+        fixable = 0
 
     if config_s['Contact-Email'] != info_s['Contact']:
         warn("Mismatched contacts: %s in configuration; %s published.",
@@ -674,6 +695,7 @@
         previousMidnight(config_s['PublicKeyLifetime'].getSeconds() +
                          info_s['Valid-After'])):
         warn("Published lifetime does not match PublicKeyLifetime")
+        warn("(This problem will go away in a while).")
 
     if info_s['Software'] != 'Mixminion %s'%mixminion.__version__:
         warn("Published version (%s) does not match current version (%s)",
@@ -689,7 +711,7 @@
     if config_im['IP'] == '0.0.0.0':
         guessed = _guessLocalIP()
         if guessed != config_im['IP']:
-            warn("Guessed IP (%s) does not match publishe IP (%s)",
+            warn("Guessed IP (%s) does not match published IP (%s)",
                  guessed, info_ip)
     elif config_im['IP'] != info_ip:
         warn("Configured IP (%s) does not match published IP (%s)",
@@ -722,7 +744,7 @@
 
 def generateServerDescriptorAndKeys(config, identityKey, keydir, keyname,
                                     hashdir, validAt=None, now=None,
-                                    useServerKeys=0):
+                                    useServerKeys=0, validUntil=None):
     #XXXX reorder args
     """Generate and sign a new server descriptor, and generate all the keys to
        go with it.
@@ -734,7 +756,7 @@
           hashdir -- The root directory for storing hash logs.
           validAt -- The starting time (in seconds) for this key's lifetime.
 
-          DOCDOC useServerKeys
+          DOCDOC useServerKeys, validUntil
           """
 
     if useServerKeys:
@@ -779,7 +801,9 @@
     # Calculate descriptor and X509 certificate lifetimes.
     # (Round validAt to previous mignight.)
     validAt = mixminion.Common.previousMidnight(validAt+30)
-    validUntil = validAt + config['Server']['PublicKeyLifetime'].getSeconds()
+    if not validUntil:
+        keyLifetime = config['Server']['PublicKeyLifetime'].getSeconds()
+        validUntil = previousMidnight(validAt + keyLifetime + 30)
     certStarts = validAt - CERTIFICATE_EXPIRY_SLOPPINESS
     certEnds = validUntil + CERTIFICATE_EXPIRY_SLOPPINESS
 

Index: ServerMain.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/server/ServerMain.py,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- ServerMain.py	26 May 2003 21:08:13 -0000	1.56
+++ ServerMain.py	27 May 2003 17:24:49 -0000	1.57
@@ -8,6 +8,33 @@
    See the "MixminionServer" class for more information about how it
    all works. """
 
+## Directory layout:
+#    MINION_HOME/work/queues/incoming/ [Queue of received,unprocessed pkts]
+#                            mix/ [Mix pool]
+#                            outgoing/ [Messages for mmtp delivery]
+#                            deliver/mbox/ [DOCDOC]
+#                            deliver/smtp/
+#                            deliver/*/
+#                      tls/dhparam [Diffie-Hellman parameters]
+#                      hashlogs/hash_1*  [HashLogs of packet hashes
+#                               hash_2*    corresponding to key sets]
+#                                ...
+#                      stats.tmp [DOCDOC]
+#                log [Messages from the server]
+#                keys/identity.key [Long-lived identity PK]
+#                     key_0001/ServerDesc [Server descriptor]
+#                              mix.key [packet key]
+#                              mmtp.key [mmtp key]
+#                              mmtp.cert [mmmtp key x509 cert]
+#                              published [present if this desc is published]
+#                     key_0002/...
+#                conf/miniond.conf [configuration file]
+#                stats [DOCDOC]
+#                
+
+# FFFF Support to put keys/queues in separate directories.
+
+
 __all__ = [ 'MixminonServer' ]
 
 import getopt
@@ -534,9 +561,21 @@
         self.pidFile = os.path.join(homeDir, "pid")
 
         #XXXX004 Catch ConfigError for bad serverinfo.
-        #XXXX004 Check whether config matches serverinfo
-        self.keyring = mixminion.server.ServerKeys.ServerKeyring(config)
+        try:
+            self.keyring = mixminion.server.ServerKeys.ServerKeyring(config)
+        except ConfigError, e:
+            if str(e).startswith("Unrecognized descriptor version: 0.1"):
+                raise UIError("This server homedir contains keys in an old "
+                              "format.\nConsider running 'mixminion server"
+                              "-upgrade'")
+            elif str(e).startswith("Unrecognized descriptor version"):
+                raise UIError("The server homedir contains keys for an "
+                              "unrecognized version of the server.")
+            else:
+                raise
         self.keyring.createKeysAsNeeded()
+        self.keyring.checkDescriptorConsistency()
+        
         if self.config['DirectoryServers'].get('Publish'):
             self.keyring.publishKeys()
 
@@ -1072,3 +1111,4 @@
     LOG.info("Telling server to publish descriptors")
 
     _signalServer(config, reload=1)
+