def read_message( receiver_vol_inst, pubkey_str, privkey_str, gateway_privkey_pem, folder, msg_timestamp, msg_id, sender_vol_inst=None, storage_root="/tmp/syndicate-unused" ): # is this an incoming message? mpath = incoming_message_path( msg_timestamp, msg_id ) if storage.path_exists( mpath, volume=receiver_vol_inst ): # get the incoming message record incoming_message = read_incoming_message( privkey_str, msg_timestamp, msg_id, volume=receiver_vol_inst ) if incoming_message is None: log.error("Failed to read incoming message %s" % message_handle( msg_timestamp, msg_id ) ) return None # open the volume, if need be if sender_vol_inst is None: sender_vol_inst = sender_volume_from_incoming_message( incoming_message, gateway_privkey_pem, storage_root ) if sender_vol_inst is None: log.error("Failed to open Volume") return None # get the sender's public key sender_contact = contact.read_contact( pubkey_str, privkey_str, incoming_message.sender_addr ) if sender_contact is None: log.error("No contact record for %s; cannot verify message authenticity" % incoming_message.sender_addr ) return None # get the corresponding message from the remote Volume msg = read_message_from_volume( sender_vol_inst, sender_contact.pubkey_pem, pubkey_str, privkey_str, incoming_message ) if msg is not None: # verify that it matches the incoming message if incoming_message.message_signature != msg.signature: log.error("Message signature mismatch") return None return msg else: log.error("Failed to read message from %s" % sender_contact.addr) return None else: # it's a stored message return read_stored_message( privkey_str, folder, msg_timestamp, msg_id, volume=receiver_vol_inst )
def validate_and_parse_incoming_message( pubkey_str, privkey_str, my_addr, encrypted_incoming_message ): if encrypted_incoming_message.receiver_addr != my_addr: log.error("Message is not for me") return False sender_addr = encrypted_incoming_message.sender_addr verified = False # do we have a contact? contact_rec = contact.read_contact( pubkey_str, privkey_str, sender_addr ) if contact_rec is None: # no contact log.warning("Message from %s could not be verified." % sender_addr ) raise Exception("FIXME: Get %s's public key here" % sender_addr ) verified = False else: # check signature verified = verify_message( contact_rec.pubkey_pem, EncryptedIncomingMessage, encrypted_incoming_message ) if not verified: raise Exception("Message is not authentically from %s" % contact_rec.addr) # attempt to decrypt incoming_message_json = storage.decrypt_data( contact_rec.pubkey_pem, privkey_str, encrypted_incoming_message.incoming_message_ciphertext ) if incoming_message_json is None: log.error("Failed to decrypt incoming message") return False # attempt to parse try: incoming_message = storage.json_to_tuple( SyndicateIncomingMessage, incoming_message_json ) except Exception, e: log.exception(e) log.error("Failed to unserialize message from %s" % sender_addr ) return False
signature="" ) # generate the message with the attachment info msg_attrs = dict( [(field, getattr(_message, field)) for field in _message._fields] ) signature = sign_message( privkey_str, SyndicateMessage, msg_attrs ) msg_attrs['signature'] = signature message = SyndicateMessage( **msg_attrs ) # get contact public keys from Volume all_parsed_addrs = reduce( lambda x, y: x + y, parsed_addrs.values(), [] ) for addr in all_parsed_addrs: if contact.contact_exists( pubkey_str, addr.addr ): # get the contact public key contact_rec = contact.read_contact( pubkey_str, privkey_str, addr.addr ) if contact_rec is None: missing.append( addr ) else: # send to this contact contacts.append( contact_rec ) else: missing.append( addr ) log.debug("No public key for %s" % addr.addr) # get remaining contact public keys from the user's MS and store them for missing_addr in missing: # new contact... pubkey_pem = network.download_user_pubkey( missing_addr.addr ) if pubkey_pem is None: