예제 #1
0
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)
예제 #2
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)
예제 #3
0
    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
예제 #4
0
    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)
예제 #5
0
    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()
예제 #6
0
    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
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
 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
예제 #10
0
    # 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 = "*"
예제 #11
0
 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)
예제 #12
0
 def loadServer(self, key, keepContents=0, assumeValid=1):
     #XXXX008 digest-cache
     return ServerInfo(fname=os.path.join(self._loc, key),
                       assumeValid=assumeValid,
                       _keepContents=keepContents)