def decode_sig(sig, msg_data, callback): if DEBUG > 2: print '--> Starting decode_sig' keyobj = Key() if DEBUG > 2: print 'Creating keyobj', keyobj # _ga_import_sig (magic, sig) = gale_pack.pop_data(sig, len(SIG_MAGIC)) if SIG_MAGIC != magic: pygale.call_error_handler("invalid signature format") keyobj.set_verified(0) callback(keyobj) return (siglen, sig) = gale_pack.pop_int(sig) if siglen > GALE_SIGNATURE_LEN: pygale.call_error_handler('invalid signature format') keyobj.set_verified(0) callback(keyobj) return (sigdata, sig) = gale_pack.pop_data(sig, siglen) # These are the keybits doing the signing (keydata, sig) = gale_pack.pop_data(sig, len(sig)) keyobj.setdata(keydata) # Try to find a public key for this signature if DEBUG > 2: print 'decode_sig: importing key' import_pubkey(keyobj, lambda k, d=sigdata, m=msg_data, c=callback: decode_sig2(k, d, m, c))
def decode_sig4(key, sigdata, msg_data, callback): if key.public() is not None: if DEBUG: print 'decode_sig4: key found', key.name() # We found something via AKD if verify_sig(key, sigdata, msg_data): # And it verifies! if DEBUG: print 'decode_sig4: %s verifies OK' % key.name() key.set_verified(1) authcache.save_pubkey_todisk(key) callback(key) return else: if DEBUG: print 'decode_sig4: %s does not verify' % key.name() key.setpublic(None) key.set_verified(0) callback(key) return else: # Otherwise, give up! if DEBUG: print 'decode_sig4: no key found for', key.name() pygale.call_error_handler("Warning: no public key for %s" % key.name()) key.set_verified(0) callback(key) return
def fetch_url3(self): # Data ready for reading while 1: read, write, ex = select.select([self.sock], [], [], 0) if self.sock in read: try: chunk = self.sock.recv(1024) except socket.error, e: pygale.call_error_handler('Error fetching %s: %s' % (self.url, e)) engine.engine.del_callback(self.sock) engine.engine.del_timeout(self.timeout_handle) self.callback(None) return if not chunk: # Server closed connection self.cleanup() return self.data = self.data + chunk if self.maxsize and len(self.data) > self.maxsize: # We've seen enough self.cleanup() return else: return
def fetch_url2(self): # Connected to socket; send request engine.engine.del_write_callback(self.sock) try: self.sock.send(self.urlrequest) except socket.error, e: pygale.call_error_handler('Error fetching %s: %s' % (self.url, e)) self.callback(None) return
def start_fetching(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = s s.setblocking(0) try: s.connect((self.host, self.port)) except socket.error, e: if e[0] == errno.EINPROGRESS or e[0] == 10035: engine.engine.add_write_callback(s, self.fetch_url2) else: pygale.call_error_handler('Error fetching thumbnail: %s' % str(e))
def decode_done(key, upper_key, callback): if not key.verified(): if DEBUG > 2: print 'decode_done: cannot use %s to verify %s' %\ (key.name(), upper_key.name()) pygale.call_error_handler('unable to verify signature %s' % key.name()) callback(key) return if DEBUG > 1: print 'decode_done: key %s verified key %s' % (key.name(), upper_key.name()) upper_key.set_verified(1) if DEBUG > 2: print 'decode_done: adding %s to memory cache' %\ upper_key.name() authcache.add_to_memory_cache(upper_key) callback(upper_key) return
def verify_sig(key, sigdata, msg_data): """Return 1 iff the sigdata is the signed message digest for msg_data, signed with the key key""" if DEBUG > 2: print 'verify_sig: verifying sig with key %s (%s)' %\ (key, key.name()) if key.trusted(): if DEBUG > 2: print 'verify_sig: trusted key' key.set_verified(1) return 1 assert key.public() context = openssl.evp.MD_CTX() context.VerifyInit(openssl.evp.md5()) context.VerifyUpdate(msg_data) retval = context.VerifyFinal(sigdata, key.public()) if retval != 1: pygale.call_error_handler( 'signature %s does not verify (key mismatch?)' % key.name()) return 0 else: return 1
def import_pubkey(keyobj, callback, trust=0): if DEBUG > 2: print '--> Starting import_pubkey' keydata = keyobj.data() # _ga_import_pub # Back up the key to verify its signature, later save = keydata (magic, keydata) = gale_pack.pop_data(keydata, len(KEY_MAGIC)) if KEY_MAGIC == magic: version = 1 elif KEY_MAGIC2 == magic: version = 2 elif KEY_MAGIC3 == magic: (subversion, keydata) = gale_pack.pop_data(keydata, len(SUBVERSION)) if SUBVERSION == subversion: version = 3 else: pygale.call_error_handler('Unsupported version 3 key format') keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return else: pygale.call_error_handler('Unsupported public key (bad magic)') keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return # version must be <= 3 at this point if DEBUG >= 3: print 'Public key version:', version if version > 1: (namelen, keydata) = gale_pack.pop_int(keydata) (pubkeyname, keydata) = gale_pack.pop_string(keydata, namelen, chars=1) else: # version == 1 (pubkeyname, keydata) = gale_pack.pop_nulltermstr(keydata) pubkeyname = flip_local_key_part(pubkeyname) if DEBUG > 2: print 'Unpacking public key named:', pubkeyname keyobj.setname(pubkeyname) if DEBUG > 2: print 'Setting name in %s to %s' % (`keyobj`, pubkeyname) keyobj.settrusted(trust) if len(keydata) == 0: if DEBUG: print 'Found stub key for', pubkeyname keyobj.setpublic(None) callback(keyobj) return # Otherwise, deal with a non-stub key # Special-case for different version keys. Version 3 is the key with # fragments in it, which Dan introduced in 0.91b. if version == 3: fraglist = gale_pack.group_to_FragList(keydata, DAN_IS_STOOPID=1) # Verify key if it's signed if fraglist.has_key('security/signature'): # deal with only the first security/signature fragment sig = fraglist.get_binary_first('security/signature') (sig_len, sig) = gale_pack.pop_int(sig) (signature, sig) = gale_pack.pop_data(sig, sig_len) msg_data = sig new_fragments = gale_pack.group_to_FragList(sig) fraglist.update(new_fragments) else: signature = '' # TODO # This hacky setting of msg_data is to fix the bug later on # where we try to call decode_sig with msg_data. I need to # dig into key formats more to find the right thing to do. msg_data = '' # TODO dangermouse # Redirects should not be handled here since the field contains # a *location* and not a key name if fraglist.get_text('key.redirect'): # Handle a key redirection: the field contains a *location* keyobj.set_redirect(fraglist.get_text_first('key.redirect')) # Use only the first instance of each fragment if it exists comment = fraglist.get_text_first('key.owner', 'Unspecified owner') time_sign = fraglist.get_time_first('key.signed', 0) time_expire = fraglist.get_time_first('key.expires', 0) rsa_keybits = fraglist.get_int_first('rsa.bits', 0) rsa_modulus = fraglist.get_binary_first('rsa.modulus', '') rsa_exponent = fraglist.get_binary_first('rsa.exponent', '') # Set the list of key members but do not look them up at this # point if fraglist.has_key('key.member'): keyobj.set_members(fraglist.get_text('key.member')) # Done unpacking version 3 key # Version 1 or 2 keys are packed binary data. elif version == 1 or version == 2: if version == 2: (comment, keydata) = gale_pack.pop_lenstr(keydata, chars=1) else: (comment, keydata) = gale_pack.pop_nulltermstr(keydata) if DEBUG > 2: print 'Found comment:', comment (rsa_keybits, keydata) = gale_pack.pop_int(keydata) (rsa_modulus, keydata) = gale_pack.pop_rle(keydata, GALE_RSA_MODULUS_LEN) (rsa_exponent, keydata) = gale_pack.pop_rle(keydata, GALE_RSA_MODULUS_LEN) if rsa_keybits > GALE_RSA_MODULUS_BITS: pygale.call_error_handler( 'bad public key bit size %i' % rsa_keybits) keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return if version > 1 and keydata: (time_sign, keydata) = gale_pack.pop_time(keydata) (time_expire, keydata) = gale_pack.pop_time(keydata) if DEBUG > 2: print 'Key signed at:', time_sign.ctime() if DEBUG > 2: print 'Key expires at:', time_expire.ctime() # if time_expire <= time.time(): # pygale.call_error_handler('found expired key for %s' % # pubkeyname) # callback(None) # return else: # no key timestamp checking in version 1 pass signature = keydata # Done unpacking version 1 or version 2 key else: # unsupported version pygale.call_error_handler('unsupported key version: %i' % version) keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return # TODO: check for expired keys keyobj.setcomment(comment) if rsa_keybits: pubkey = openssl.evp.PKEY() pubkey.assign_RSA(openssl.rsa.RSA()) pubkey.pkey.rsa.n = openssl.bn.bin2bn(rsa_modulus) pubkey.pkey.rsa.e = openssl.bn.bin2bn(rsa_exponent) keyobj.setpublic(pubkey) else: # No public key bits in this key keyobj.setpublic(None) # Import and validate the signature on this public key if not keyobj.trusted(): if DEBUG > 2: print 'import_pubkey: Verifying sig' if version < 3: msg_data = save[:-len(keydata)] if not signature or not msg_data: pygale.call_error_handler('unsigned key %s' % keyobj.name()) keyobj.setpublic(None) keyobj.set_verified(0) callback(keyobj) return decode_sig(signature, msg_data, lambda k, u=keyobj, c=callback: decode_done(k, u, c)) else: if DEBUG: print 'Key is trusted; not verifying' keyobj.set_verified(1) callback(keyobj) return