Exemple #1
0
def authenticate(request, reqKu, host, port, client, config, callable, 
        *callargs):
    # 1- make sure that reqKu hashes to reqID
    # 2- send a challenge/groupchallenge to reqID (encrypt with reqKu)
    challengeResponse = request.getUser()
    groupResponse = request.getPassword()

    if not challengeResponse or not groupResponse:
        loggerauth.info("returning challenge for request from %s:%d" \
                % (host, port))
        return sendChallenge(request, reqKu, config.nodeID)
    else:
        if getChallenge(challengeResponse):
            expireChallenge(challengeResponse)
            if groupResponse == hashstring(
                    str(reqKu.exportPublicKey())
                    +str(config.groupIDr)): 
                updateNode(client, config, host, port, reqKu, reqKu.id())
                return callable(*callargs)
            else:
                err = "Group Challenge Failed"
                loggerauth.info(err)
                loggerauth.debug("Group Challenge received was %s" \
                        % groupResponse)
                # XXX: update trust, routing
                request.setResponseCode(http.FORBIDDEN, err);
                return err
        else:
            err = "Challenge Failed"
            loggerauth.info(err)
            loggerauth.debug("Challenge received was %s" % challengeResponse)
            # XXX: update trust, routing
            request.setResponseCode(http.FORBIDDEN, err);
            return err
Exemple #2
0
 def doOp(self, command, fname):
     #print "got command '%s'" % command
     if command == "PUTF":
         logger.debug("PUTF %s", fname);
         return FileOps.StoreFile(self.factory.node, fname).deferred
     elif command == "GETI":
         logger.debug("GETI %s", fname);
         return FileOps.RetrieveFile(self.factory.node, fname).deferred
     elif command == "GETF":
         logger.debug("GETF %s", fname);
         return FileOps.RetrieveFilename(self.factory.node, fname).deferred
     elif command == "FNDN":
         logger.debug("FNDN %s" % fname);
         try: 
             intval = long(fname, 16)
         except: 
             return defer.fail("fname was not hex")
         return self.factory.node.client.kFindNode(intval)
         # The following is for testing aggregation of kFindNode on same key
         #dl = []
         #for i in [1,2,3,4,5]:
         #   d = self.factory.node.client.kFindNode(intval)
         #   dl.append(d)
         #dlist = defer.DeferredList(dl)
         #return dlist
     elif command == "FNDV":
         logger.debug("FNDV %s", fname);
         try: 
             intval = long(fname, 16)
         except: 
             return defer.fail("fname was not hex")
         return self.factory.node.client.kFindValue(intval)
     elif command == "CRED":
         passphrase, email = fdecode(fname)
         # XXX: allow an optional passphrase hint to be sent in email.
         passphrase = self.factory.node.config.Kr.decrypt(passphrase)
         logger.debug("CRED %s to %s", passphrase, email);
         Kr = self.factory.node.config.Kr.exportPrivateKey()
         Kr['g'] = self.factory.node.config.groupIDr
         fKr = fencode(Kr)
         key = AES.new(binascii.unhexlify(hashstring(passphrase)))
         fKr = '\x00'*(16-(len(fKr)%16))+fKr
         efKr = fencode(key.encrypt(fKr))
         logger.debug("efKr = %s " % efKr)
         d = smtp.sendmail('localhost', "your_flud_client@localhost", 
                 email,
                 "Subject: Your encrypted flud credentials\n\n"
                 "Hopefully, you'll never need to use this email.  Its "
                 "sole purpose is to help you recover your data after a "
                 "catastrophic and complete loss of the original computer "
                 "or hard drive.\n\n"
                 "In that unlucky event, you'll need a copy of your flud "
                 "credentials, which I've included below, sitting between "
                 "the \"---+++---\" markers.  These credentials were "
                 "encrypted with a passphrase of your choosing when you "
                 "installed the flud software.  I'll only say this "
                 "once:\n\n"
                 "YOU MUST REMEMBER THAT PASSWORD IN ORDER TO RECOVER YOUR "
                 "CREDENTIALS.  If you are unable to remember the "
                 "passphrase and your computer fails catastrophically "
                 "(losing its local copy of these credentials), you will "
                 "not be able to recover your data."
                 "\n\n"
                 "Luckily, that's all you should ever need in order to "
                 "recover all your data: your passphrase and these "
                 "credentials."
                 "\n\n"
                 "Please save this email.  You may want to print out hard "
                 "copies and store them safely, forward this email to "
                 "other email accounts, etc.  Since the credentials are "
                 "encrypted, others won't be able to steal them "
                 "without guessing your passphrase. "
                 "\n\n"
                 "---+++---\n"+efKr+"\n---+++---\n")
         return d
         # to decode this email, we search for the '---+++---' markers, make
         # sure the intervening data is all in one piece (remove any line
         # breaks \r or \n inserted by email clients) and call this 'cred',
         # reconstruct the AES key with the H(passphrase) (as above), and
         # then use the key to .decrypt(fdecode(cred)) and call this dcred,
         # then fdecode(dcred[dcred.find('d'):]) and call this ddcred, and
         # finally importPrivateKey(ddcred) and set groupIDr to ddcred['g'].
     elif command == "LIST":
         logger.debug("LIST")
         return defer.succeed(self.factory.config.master)
     elif command == "GETM":
         logger.debug("GETM")
         return FileOps.RetrieveMasterIndex(self.factory.node).deferred
     elif command == "PUTM":
         logger.debug("PUTM")
         return FileOps.UpdateMasterIndex(self.factory.node).deferred
     else:
         #print "fname is '%s'" % fname
         host = fname[:fname.find(':')]
         port = fname[fname.find(':')+1:fname.find(',')]
         fname = fname[fname.find(',')+1:]
         print "%s: %s : %s , %s" % (command, host, port, fname)
         if command == "STOR":
             logger.debug("STOR");
             return self.factory.node.client.sendStore(fname, None, 
                     host, int(port))
         elif command == "RTRV":
             logger.debug("RTRV");
             return self.factory.node.client.sendRetrieve(fname, host, 
                     int(port))
         elif command == "VRFY":
             logger.debug("VRFY");
             offset = port[port.find(':')+1:port.find('-')]
             length = port[port.find('-')+1:]
             port = port[:port.find(':')]
             print "%s: %s : %s %s - %s , %s" % (command, host, port, 
                     offset, length, fname)
             return self.factory.node.client.sendVerify(fname, int(offset), 
                     int(length), host, int(port))
         else:
             logger.debug("bad op");
             return defer.fail("bad op")
Exemple #3
0
    def _sendVerify(self, request, filekey, offset, length, reqKu, nodeID, 
            meta):
        fname = os.path.join(self.config.storedir,filekey)
        loggervrfy.debug("request for %s" % fname)
        if os.path.exists(fname):
            loggervrfy.debug("looking in regular blockfile for %s" % fname)
            if meta:
                f = BlockFile.open(fname, 'rb+')
            else:
                f = BlockFile.open(fname, 'rb')
        else:
            # check for tarball for originator
            loggervrfy.debug("checking tarball for %s" % fname)
            tarballs = []
            tarballbase = os.path.join(self.config.storedir, reqKu.id())+".tar"
            if os.path.exists(tarballbase+".gz"):
                tarballs.append((tarballbase+".gz", 'r:gz'))
            if os.path.exists(tarballbase):
                tarballs.append((tarballbase, 'r'))
            loggervrfy.debug("tarballs is %s" % tarballs)
            for tarball, openmode in tarballs:
                loggervrfy.debug("looking in tarball %s..." % tarball)
                tar = tarfile.open(tarball, openmode)
                try:
                    tarf = tar.extractfile(filekey)
                    tari = tar.getmember(filekey)
                    # XXX: update timestamp on tarf in tarball
                    fsize = tari.size
                    if offset > fsize or (offset+length) > fsize:
                        # XXX: should limit length
                        loggervrfy.debug("VERIFY response failed (from %s):"
                                " bad offset/length" % tarball)
                        msg = "Bad request: bad offset/length in VERIFY"
                        request.setResponseCode(http.BAD_REQUEST, msg) 
                        return msg
                    # XXX: could avoid seek/read if length == 0
                    tarf.seek(offset)
                    # XXX: bad blocking read
                    data = tarf.read(length)
                    tarf.close()
                    if meta:
                        mfname = "%s.%s.meta" % (filekey, meta[0])
                        loggervrfy.debug("looking for %s" % mfname)
                        if mfname in tar.getnames():
                            # make sure that the data is the same, if not,
                            # remove it and re-add it
                            tarmf = tar.extractfile(mfname)
                            # XXX: bad blocking read
                            stored_meta = tarmf.read()
                            tarmf.close()
                            if meta[1] != stored_meta:
                                loggervrfy.debug("updating tarball"
                                        " metadata for %s.%s" 
                                        % (filekey, meta[0]))
                                tar.close()
                                TarfileUtils.delete(tarball, mfname)
                                if openmode == 'r:gz':
                                    tarball = TarfileUtils.gunzipTarball(
                                            tarball)
                                tar = tarfile.open(tarball, 'a')
                                metaio = StringIO(meta[1])
                                tinfo = tarfile.TarInfo(mfname)
                                tinfo.size = len(meta[1])
                                tar.addfile(tinfo, metaio)
                                tar.close()
                                if openmode == 'r:gz':
                                    tarball = TarfileUtils.gzipTarball(
                                            tarball)
                            else:
                                loggervrfy.debug("no need to update tarball"
                                        " metadata for %s.%s" 
                                        % (filekey, meta[0]))
                        else:
                            # add it
                            loggervrfy.debug("adding tarball metadata"
                                    " for %s.%s" % (filekey, meta[0]))
                            tar.close()
                            if openmode == 'r:gz':
                                tarball = TarfileUtils.gunzipTarball(tarball)
                            tar = tarfile.open(tarball, 'a')
                            metaio = StringIO(meta[1])
                            tinfo = tarfile.TarInfo(mfname)
                            tinfo.size = len(meta[1])
                            tar.addfile(tinfo, metaio)
                            tar.close()
                            if openmode == 'r:gz':
                                tarball = TarfileUtils.gzipTarball(
                                        tarball)
                        
                    tar.close()
                    hash = hashstring(data)
                    loggervrfy.info("successful VERIFY (from %s)" % tarball)
                    return hash
                except:
                    tar.close()
            loggervrfy.debug("requested file %s doesn't exist" % fname)
            msg = "Not found: not storing %s" % filekey
            request.setResponseCode(http.NOT_FOUND, msg)
            return msg

        # make sure request is reasonable   
        fsize = os.stat(fname)[stat.ST_SIZE]
        if offset > fsize or (offset+length) > fsize:
            # XXX: should limit length
            loggervrfy.debug("VERIFY response failed (bad offset/length)")
            msg = "Bad request: bad offset/length in VERIFY"
            request.setResponseCode(http.BAD_REQUEST, msg) 
            return msg
        else:
            # XXX: blocking
            # XXX: could avoid seek/read if length == 0 (noop for meta update)
            f.seek(offset)
            data = f.read(length)
            if meta:
                loggervrfy.debug("adding metadata for %s.%s" 
                        % (fname, meta[0]))
                f.addNode(int(nodeID, 16) , {meta[0]: meta[1]})
            # XXX: blocking
            f.close()
            hash = hashstring(data)
            loggervrfy.debug("returning VERIFY")
            return hash