def _readServer(contents): """Read a ServerInfo from the string 'contents', which is either a server descriptor or the name of a file holding a descriptor. Raise MixError on failure.""" if stringContains(contents, "[Server]"): pass else: contents = readPossiblyGzippedFile(contents) # May raise ConfigError, MixError return contents, ServerInfo(string=contents, assumeValid=0)
def directoryTiming(): print "#========== DESCRIPTORS AND DIRECTORIES ==============" from mixminion.server.ServerKeys import ServerKeyring confStr = """ [Server] EncryptIdentityKey: no PublicKeyLifetime: 1 day EncryptPrivateKey: no Homedir: %s Mode: relay Nickname: The-Server Contact-Email: [email protected] [Incoming/MMTP] Enabled: yes IP: 1.1.1.1 """ % mix_mktemp() config = ServerConfig(string=confStr) keyring = ServerKeyring(config) keyring.getIdentityKey() print "Create and sign server descriptor", timeit(keyring.createKeys, 10) liveKey = keyring.getServerKeysets()[0] descFile = liveKey.getDescriptorFileName() desc = open(descFile).read() ## for _ in xrange(2000): ## ServerInfo(string=desc, assumeValid=0) ## if 1: return print "Parse server descriptor (no validation)", \ timeit(lambda desc=desc: ServerInfo(string=desc,assumeValid=1), 400) print "Parse server descriptor (full validation)", \ timeit(lambda desc=desc: ServerInfo(string=desc,assumeValid=0), 400) info = ServerInfo(string=desc) dbin = cPickle.dumps(info, 1) print "Unpickle binary-pickled descriptor (%s/%s)"%(len(dbin),len(desc)), \ timeit(lambda dbin=dbin: cPickle.loads(dbin), 400) dtxt = cPickle.dumps(info, 0) print "Unpickle text-pickled descriptor (%s/%s)"%(len(dtxt),len(desc)), \ timeit(lambda dtxt=dtxt: cPickle.loads(dtxt), 400)
def _repOK(self): self.clean() keys = self._statusDB.keys() fnames = os.listdir(self._loc) keys.sort() fnames.sort() if keys != fnames: return 0 for f in fnames: status = self._statusDB[f] try: #XXXX digest-cache server = ServerInfo(fname=os.path.join(self._loc, f)) except: return 0 if status._digest != server.getDigest(): return 0 if status._published != server['Server']['Published']: return 0 if status._validAfter != server['Server']['Valid-After']: return 0 if status._validUntil != server['Server']['Valid-Until']: return 0 if status._nickname != server['Server']['Nickname']: return 0 if status._identityDigest != server.getKeyStatus(): return 0 return 1
def rescan(self): self._statusDB.close() os.path.unlink(self._dbLoc) self.clean() self._statusDB = mixminion.Filestore.WritethroughDict( self._dbLoc, "server cache") for key in os.listdir(self._loc): fn = os.path.join(self._loc, key) try: #XXXX digest-cache server = ServerInfo(fname=fn) except (OSError, MixError, ConfigError), e: LOG.warn("Deleting invalid server %s: %s", key, e) os.unlink(fn) server = None if server is None: continue k2 = self._getKey(server.getDigest()) if k2 != key: LOG.info("Renaming server in %s to correct file %s",key,k2) os.rename(fn, os.path.join(self._loc, k2)) key = k2 self._updateCache(key, server)
def rescan(self): """Reconstruct this ServerList object's internal state.""" try: self._lock() # First, build self.servers self.servers = {} for filename in os.listdir(self.serverDir): path = os.path.join(self.serverDir, filename) try: self.servers[filename] = ServerInfo(fname=path) except ConfigError, e: LOG.warn("Somehow, a bad server named %s got in our store", filename) LOG.warn(" (Error was: %s)", str(e)) _moveServer(self.serverDir, self.rejectDir, filename) # Next, rebuild self.serverIDs: self.serverIDs = {} for filename in os.listdir(self.serverIDDir): path = os.path.join(self.serverIDDir, filename) t = readPickled(path) if t[0] != 'V0': LOG.warn("Skipping confusing stored key in file %s", filename) continue nickname, key = t[1] key = pk_decode_public_key(key) if self.serverIDs.has_key(nickname.lower()): LOG.warn("Eeek! Multiple entries for %s", nickname) if not pk_same_public_key(self.serverIDs[nickname.lower()], key): raise MixFatalError( "Multiple conflicting entries for %s" % nickname) self.serverIDs[nickname.lower()] = key # (check for consistency) for s in self.servers.values(): lcn = s.getNickname().lower() try: ident = self.serverIDs[lcn] except KeyError: raise UIError("No stored key for server %s" % s.getNickname()) if not pk_same_public_key(ident, s.getIdentity()): raise UIError("Inconsistent stored key for server %s" % s.getNickname()) # Then, rebuild self.serversByNickname self.__buildNicknameMap()
def rescan(self): self._statusDB.close() os.path.unlink(self._dbLoc) self.clean() self._statusDB = mixminion.Filestore.WritethroughDict( self._dbLoc, "server cache") for key in os.listdir(self._loc): fn = os.path.join(self._loc, key) try: #XXXX digest-cache server = ServerInfo(fname=fn) except (OSError, MixError, ConfigError), e: LOG.warn("Deleting invalid server %s: %s", key, e) os.unlink(fn) server = None if server is None: continue k2 = self._getKey(server.getDigest()) if k2 != key: LOG.info("Renaming server in %s to correct file %s", key, k2) os.rename(fn, os.path.join(self._loc, k2)) key = k2 self._updateCache(key, server)
def receiveServer(self, text, source): """Process a new server descriptor and store it for later action. (To be run by the CGI user.) If the server will be automatically inserted, return true. If the server will be inserted (given administrator intervention), raise ServerQueuedException. If there is a problem, log it, and raise UIError. text -- a string containing a new server descriptor. source -- a (human readable) string describing the source of the descriptor, used in error messages. """ try: server = ServerInfo(string=text,assumeValid=0) except MixError, e: LOG.warn("Rejected invalid server from %s: %s", source,e) raise UIError("Server descriptor was not valid: %s"%e)
def getServerDescriptor(self): """Return a ServerInfo for this keyset, reading it from disk if needed.""" if self.serverinfo is None: self.serverinfo = ServerInfo(fname=self.descFile) return self.serverinfo
# Remove extra (leading or trailing) whitespace from the lines. lines = [line.strip() for line in info.split("\n")] # Remove empty lines lines = filter(None, lines) # Force a newline at the end of the file, rejoin, and sign. lines.append("") info = "\n".join(lines) info = signServerInfo(info, identityKey) # Write the desciptor writeFile(serverKeys.getDescriptorFileName(), info, mode=0644) # This is for debugging: we try to parse and validate the descriptor # we just made. # FFFF Remove this once we're more confident. inf = ServerInfo(string=info) ok = checkDescriptorConsistency(inf, config, log=0, isPublished=0) if ok not in ('good', 'so-so'): print "========" print info print "======" checkDescriptorConsistency(inf, config, log=1, isPublished=0) assert ok in ('good', 'so-so') return info def _rule(allow, (ip, mask, portmin, portmax)): """Return an external representation of an IP allow/deny rule.""" if mask == '0.0.0.0': ip = "*"
def _addOneFromRawDirLines(self, lines): s = "".join(lines) #XXXX digest-cache si = ServerInfo(s, assumeValid=0, keepContents=1) if not self.store.hasServer(si): self.store.addServer(si)
def loadServer(self, key, keepContents=0, assumeValid=1): #XXXX008 digest-cache return ServerInfo(fname=os.path.join(self._loc, key), assumeValid=assumeValid, _keepContents=keepContents)