def handle_merge(self, filename): f = file(filename) contents = f.readlines() f.close() ver1 = [] ver2 = [] current = 'both' startv1 = '<<<<<<<' startboth = '>>>>>>>' startv2 = '=======' for line in contents: line = line.strip() if line.startswith(startv1): current = 'v1' continue elif line.startswith(startv2): current = 'v2' continue elif line.startswith(startboth): current = 'both' continue if current == 'both': ver1.append(line) ver2.append(line) elif current == 'v1': ver1.append(line) else: ver2.append(line) v1 = '\n'.join(ver1) v2 = '\n'.join(ver2) rec1 = self.parse_record(v1) rec2 = self.parse_record(v2) # check signatures if not any(crypto.check_signature(crypto.parse_pub_key(k.encode()), rec1[5], *rec1) for k in self.get_pubkeys(rec1[3])): raise NumbexDBError('invalid signature on %s'%rec1) if not any(crypto.check_signature(crypto.parse_pub_key(k.encode()), rec2[5], *rec2) for k in self.get_pubkeys(rec2[3])): raise NumbexDBError('invalid signature on %s'%rec2) # compare owners if rec1[3] != rec2[3]: raise NumbexDBError('cannot merge %s and %s - owners differ'%(rec1, rec2)) # choose the more recent version from operator import itemgetter merged = max(rec1, rec2, key=itemgetter(4)) mergedtxt = self.make_record(*merged) f = file(filename, 'wb') f.write(mergedtxt) f.close()
def check_record_signature(self, cur, start, end, sip, owner, mdate, sig): keys = self._get_pub_keys(cur, owner) for key in keys: dsapub = crypto.parse_pub_key(key.encode('ascii')) if crypto.check_signature(dsapub, sig, start, end, sip, owner, mdate): return True return False
def soap_receivePublicKey(self, ps, **kw): self._init_db() request, response = NumbexServiceService.soap_receivePublicKey(self, ps, **kw) owner = request._owner pubkeystr = request._pubkey pubkey = crypto.parse_pub_key(pubkeystr) if not pubkey.check_key(): response._return = False else: response._return = True self.db.add_public_key(owner, pubkeystr) return request, response
def test_soap(self): port = self.port pemkeys = database.Database._example_privkeys extract_pubkey = lambda x: crypto.extract_pub_key( crypto.parse_priv_key(pemkeys[x])) keys = dict(freeconet=extract_pubkey('freeconet'), telarena=extract_pubkey('telarena')) basedatacsv = '''+481234,+481299,sip.freeconet.pl,freeconet,2009-01-03T23:59:30.123456 +4820000,+4820999,sip.freeconet.pl,freeconet,2009-01-03T23:59:30.123456 +4821000,+4821111,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456 +4830000,+4830099,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456''' basedata = utils.parse_csv_data(StringIO(basedatacsv)) tosend = '''+4821005,+4821011,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000 +481222,+481240,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000 +481298,+481301,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000 +4821113,+4821123,new.freeconet.pl,freeconet,2009-01-09T20:11:58.312000''' # no signatures self.assertRaises(ZSI.FaultException, send, StringIO(tosend), url=self.url) # test overwriting send_sign(StringIO(basedatacsv), StringIO(pemkeys['freeconet']), url=self.url) result = pull_all(url=self.url) parsed = utils.parse_csv_data(StringIO(result)) for rowe, rowr in zip(basedata, parsed): self.assertEqual(rowr[:-1], rowe) for row in parsed: key = crypto.parse_pub_key(keys[row[3]]) self.assert_(crypto.check_signature(key, row[5], *row)) # test updates send_sign(StringIO(tosend), StringIO(pemkeys['freeconet']), url=self.url) expected = utils.parse_csv_data(StringIO('''+481241,+481297,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456 +4821000,+4821004,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456 +4821012,+4821111,sip.freeconet.pl,freeconet,2009-01-08T23:59:30.123456''')) result = pull_sign(url=self.url) parsed = utils.parse_csv_data(StringIO(result)) for rowe, rowr in zip(expected, parsed): self.assertEqual(rowe[:-1], rowr[:-2])
def handle_room_join_packet(packet_payload, parsed, server): sender_nick = parsed['from_nick'] channel = parsed['to_channel'] account = accounts.get_my_account() if not parsed['to_channel']: # XXX functionify util.debug("Received ROOM_JOIN not in channel from %s. Ignoring." % sender_nick) return "" # Is this channel a viola room for us? try: viola_room = account.get_viola_room(channel, server) except accounts.NoSuchRoom: util.debug("Received ROOM_JOIN in a regular channel (%s). Ignoring." % channel) return "" payload = base64.b64decode(packet_payload) if len(payload) < ROOM_JOIN_PAYLOAD_LEN: raise IncompletePacket signature = payload[:SIG_LEN] identity_pubkey = crypto.parse_signing_pubkey(payload[SIG_LEN:SIG_LEN+PUBKEY_LEN]) room_pubkey = crypto.parse_pub_key(payload[SIG_LEN+PUBKEY_LEN:SIG_LEN+PUBKEY_LEN+PUBKEY_LEN]) # Verify signature # XXX is this the right logic for this particular packet? # XXX catch exception identity_pubkey.verify(payload) # XXX should we add all members even if we don't know them? viola_room.add_member(sender_nick, identity_pubkey, room_pubkey) # No need to do anything more if we are not captain in this channel. if not viola_room.i_am_captain: util.debug("Received ROOM_JOIN in %s but not captain. Ignoring." % channel) return "" util.debug("Received ROOM_JOIN in %s. Sending KEY_TRANSPORT (%d members)!" % (channel, len(viola_room.members))) # We are the captain. Check if we trust this key. Reject member otherwise. try: joining_friend_name = account.get_friend_from_identity_key(identity_pubkey) except accounts.IdentityKeyNotTrusted: buf = viola_room.buf util.viola_channel_msg(buf, "%s nickname %s is trying to join the channel with key %s." % (otrlib.colorize("Untrusted", "red"), sender_nick, crypto.get_hexed_key(identity_pubkey)), "red") util.viola_channel_msg(buf, "If you trust that key and you want them to join the channel, " "please issue the following command and ask them to rejoin the channel:\n" "\t /viola trust-key <name> %s\n" "where <name> is the nickname you want to assign to the key." % crypto.get_hexed_key(identity_pubkey), "red") util.viola_channel_msg(buf, "Example: /viola trust-key alice %s" % crypto.get_hexed_key(identity_pubkey), "red") return "" # XXX Security: Maybe we should ask the captain before autoadding them! buf = viola_room.buf util.viola_channel_msg(buf, "Friend '%s' was added to the viola room!" % joining_friend_name) # We are captains in the channel. Act like it! # There is a new room member! Refresh and send new key! send_key_transport_packet(viola_room) return ""
def handle_key_transport_packet(packet_payload, parsed, server): sender = parsed['from_nick'] channel = parsed['to_channel'] account = accounts.get_my_account() if not channel: # XXX functionify util.debug("Received KEY_TRANSPORT not in channel from %s. Ignoring." % sender) return "" # Is this channel a viola room for us? # XXX Code duplication try: viola_room = account.get_viola_room(channel, server) except accounts.NoSuchRoom: util.debug("Received ROOM_JOIN in a regular channel (%s). Ignoring." % channel) return "" payload = base64.b64decode(packet_payload) if len(payload) < MINIMUM_KEY_TRANSPORT_PAYLOAD_LEN: raise IncompletePacket if viola_room.i_am_captain: util.debug("Received KEY_TRANSPORT in %s by %s but I am captain! Ignoring." % (channel, sender)) return "" util.debug("Received KEY_TRANSPORT in %s! Handling it." % channel) # Start parsing the packet signature = payload[:SIG_LEN] captain_identity_pubkey = payload[SIG_LEN:SIG_LEN+PUBKEY_LEN] captain_identity_pubkey = crypto.parse_signing_pubkey(captain_identity_pubkey) captain_transport_pubkey = payload[SIG_LEN+PUBKEY_LEN : SIG_LEN+PUBKEY_LEN+PUBKEY_LEN] captain_transport_pubkey = crypto.parse_pub_key(captain_transport_pubkey) encrypted_message_key_array = payload[SIG_LEN+PUBKEY_LEN+PUBKEY_LEN:] # Check if we trust the captain. try: captain_friend_name = account.get_friend_from_identity_key(captain_identity_pubkey) except accounts.IdentityKeyNotTrusted: buf = viola_room.buf util.viola_channel_msg(buf, "Untrusted nickname %s is the captain of this channel with key: %s" % (sender, captain_identity_pubkey), "red") util.viola_channel_msg(buf, "Ignoring KEY_TRANSPORT by untrusted captain. If you trust that key and" "you want to join the channel, please issue the following command and rejoin:\n" "\t /viola trust-key <name> %s\n" "where <name> is the nickname you want to assign to the key." % crypto.get_hexed_key(captain_identity_pubkey), "red") util.viola_channel_msg(buf, "Example: /viola trust-key alice %s" % crypto.get_hexed_key(captain_identity_pubkey), "red") return "" # Verify captain signature captain_identity_pubkey.verify(payload) # XXX catch exception # Try to decrypt the message key array try: room_message_key = crypto.decrypt_room_message_key(encrypted_message_key_array, captain_transport_pubkey, viola_room.get_room_participant_privkey()) except crypto.NoKeyFound: util.debug("Received KEY_TRANSPORT but did not find my key. F**k.") return "" # We got the room message key! viola_room.set_room_message_key(room_message_key) viola_room.status = "done" # We found our captain. Add them to the room! # XXX should we do this here or before the checks? viola_room.add_member(sender, captain_identity_pubkey, captain_transport_pubkey) # Print some messages to the user buf = util.viola_channel_msg(viola_room.buf, "Joined room %s with captain %s!" % (channel, sender)) util.debug("Got a new room message key from captain %s: %s" % \ (sender, crypto.get_hexed_key(room_message_key))) return ""
def import_data(self, data, delete=None): '''data format: iterator of records in format produced by parse_record''' self.log.info('importing %s records...', len(data)) tstart = time.time() keycache = {} for row in data: if len(row) != 6: self.log.warning("invalid record %s", row) return False owner = row[3] if not owner in keycache: pemkeys = [k.encode('ascii') if isinstance(k, unicode) else k for k in self.get_pubkeys(owner)] keycache[owner] = [crypto.parse_pub_key(k) for k in pemkeys] if not keycache[owner]: self.log.warning("no key found for %s", row) return False checked_data = row[:-1] sig = row[-1] if not any(crypto.check_signature(key, row[-1], *row[:-1]) for key in keycache[owner]): self.log.warning("invalid signature %s", row) return False else: self.log.debug("signature valid for %s", row) shelf = self.shelf if delete is not None: for k in delete: path = self.make_repo_path(k) del shelf[path] for r in data: start, end, sip, owner, mdate, rsasig = r num = self.make_repo_path(start) newrec = self.make_record(start, end, sip, owner, mdate, rsasig) self.log.debug("inserting %s", r) # 'key in shelf' doesn't seem to work try: oldrec = shelf[num] except KeyError: shelf[num] = newrec else: if oldrec != newrec: shelf[num] = newrec self.log.debug("syncing repository, this may take a while") self.sync() self.log.debug("checking for overlaps") overlaps = self.check_overlaps() if overlaps: self.log.warning("import resulted in overlapping ranges, rolling back") parents = shelf.get_parent_ids() if len(parents) == 0: # TODO clear it all pass elif len(parents) == 1: shelf.update_head(parents[0]) else: raise NumbexDBError("import commit with multiple parents?!?") shelf.git("gc", "--auto") self.reload() return False tend = time.time() self.log.info("import successful, time %.3f", tend-tstart) return True
def test_pubkey_signature(self): v = ["+48581234", "+48581999", "sip.freeconet.pl", "freeconet", datetime.datetime.now()] dsapub = crypto.parse_pub_key(self.pubkey) sig = crypto.sign_record(self.dsa, *v) self.assert_(crypto.check_signature(dsapub, sig, *v))
def handle_key_transport_packet(packet_payload, parsed, server): sender = parsed['from_nick'] channel = parsed['to_channel'] account = accounts.get_my_account() if not channel: # XXX functionify util.debug("Received KEY_TRANSPORT not in channel from %s. Ignoring." % sender) return "" # Is this channel a flute room for us? # XXX Code duplication try: flute_room = account.get_flute_room(channel, server) except accounts.NoSuchRoom: util.debug("Received KEY_TRANSPORT in a regular channel (%s). Ignoring." % channel) return "" payload = base64.b64decode(packet_payload) if len(payload) < MINIMUM_KEY_TRANSPORT_PAYLOAD_LEN: raise IncompletePacket if flute_room.i_am_captain: util.debug("Received KEY_TRANSPORT in %s by %s but I am captain! Ignoring." % (channel, sender)) return "" util.debug("Received KEY_TRANSPORT in %s! Handling it." % channel) # Start parsing the packet signature = payload[:SIG_LEN] captain_identity_pubkey = payload[SIG_LEN:SIG_LEN+PUBKEY_LEN] captain_identity_pubkey = crypto.parse_signing_pubkey(captain_identity_pubkey) captain_transport_pubkey = payload[SIG_LEN+PUBKEY_LEN : SIG_LEN+PUBKEY_LEN+PUBKEY_LEN] captain_transport_pubkey = crypto.parse_pub_key(captain_transport_pubkey) new_key_counter, = struct.unpack('>I',payload[SIG_LEN + PUBKEY_LEN + PUBKEY_LEN: SIG_LEN + PUBKEY_LEN + PUBKEY_LEN + KEY_ID_LEN]) encrypted_message_key_array = payload[SIG_LEN+PUBKEY_LEN+PUBKEY_LEN + KEY_ID_LEN:] # Check if we trust the captain. try: captain_friend_name = account.get_friend_from_identity_key(captain_identity_pubkey) except accounts.IdentityKeyNotTrusted: hexed_captain_key = crypto.get_hexed_key(captain_identity_pubkey) buf = flute_room.buf util.flute_channel_msg(buf, "Untrusted nickname %s is the captain of this channel with key: %s" % (sender, hexed_captain_key), color="red") util.flute_channel_msg(buf, "Ignoring KEY_TRANSPORT by untrusted captain. If you trust that key and " "you want to join the channel, please issue the following command and rejoin:\n" "\t /flute trust-key <name> %s\n" "where <name> is the nickname you want to assign to the key." % hexed_captain_key, color="red") util.flute_channel_msg(buf, "Example: /flute trust-key alice %s" % hexed_captain_key, color="red") return "" # Verify captain signature captain_identity_pubkey.verify(payload) # XXX catch exception # Check for replays using KEY_TRANSPORT counter if new_key_counter < 1: util.debug("Corrupted key counter %d" % new_key_counter) return "" if flute_room.key_transport_is_replay(new_key_counter): return "" # Try to decrypt the message key array try: room_message_key = crypto.decrypt_room_message_key(encrypted_message_key_array, captain_transport_pubkey, flute_room.get_room_participant_privkey()) except crypto.NoKeyFound: util.debug("Received KEY_TRANSPORT but did not find my key. F**k.") return "" # We got the room message key! flute_room.set_room_message_key(room_message_key, new_key_counter) flute_room.status = "done" # We found our captain. Add them to the room! # XXX careful not to double-add the captain in case of rekey flute_room.add_member(sender, captain_identity_pubkey, captain_transport_pubkey) # Print some messages to the user buf = util.flute_channel_msg(flute_room.buf, "Got room key for %s from captain %s (friend name: %s)!" % (channel, sender, captain_friend_name)) util.debug("Got a new room message key from captain %s: %s" % \ (sender, crypto.get_hexed_key(room_message_key))) return ""
def handle_room_join_packet(packet_payload, parsed, server): sender_nick = parsed['from_nick'] channel = parsed['to_channel'] account = accounts.get_my_account() if not parsed['to_channel']: # XXX functionify util.debug("Received ROOM_JOIN not in channel from %s. Ignoring." % sender_nick) return "" # Is this channel a flute room for us? try: flute_room = account.get_flute_room(channel, server) except accounts.NoSuchRoom: util.debug("Received ROOM_JOIN in a regular channel (%s). Ignoring." % channel) return "" payload = base64.b64decode(packet_payload) if len(payload) < ROOM_JOIN_PAYLOAD_LEN: raise IncompletePacket signature = payload[:SIG_LEN] identity_pubkey = crypto.parse_signing_pubkey(payload[SIG_LEN:SIG_LEN+PUBKEY_LEN]) room_pubkey = crypto.parse_pub_key(payload[SIG_LEN+PUBKEY_LEN:SIG_LEN+PUBKEY_LEN+PUBKEY_LEN]) # Verify signature # XXX is this the right logic for this particular packet? # XXX catch exception identity_pubkey.verify(payload) # XXX should we add all members even if we don't know them? flute_room.add_member(sender_nick, identity_pubkey, room_pubkey) # No need to do anything more if we are not captain in this channel. if not flute_room.i_am_captain: util.debug("Received ROOM_JOIN in %s but not captain. Ignoring." % channel) return "" util.debug("Received ROOM_JOIN in %s. Sending KEY_TRANSPORT (%d members)!" % (channel, len(flute_room.members))) # We are the captain. Check if we trust this key. Reject member otherwise. try: joining_friend_name = account.get_friend_from_identity_key(identity_pubkey) except accounts.IdentityKeyNotTrusted: buf = flute_room.buf util.flute_channel_msg(buf, "%s nickname %s is trying to join the channel with key %s." % (otrlib.colorize("Untrusted", "red"), sender_nick, crypto.get_hexed_key(identity_pubkey)), "red") util.flute_channel_msg(buf, "If you trust that key and you want them to join the channel, " "please issue the following command and ask them to rejoin the channel:\n" "\t /flute trust-key <name> %s\n" "where <name> is the nickname you want to assign to the key." % crypto.get_hexed_key(identity_pubkey), "red") util.flute_channel_msg(buf, "Example: /flute trust-key alice %s" % crypto.get_hexed_key(identity_pubkey), "red") return "" # XXX Security: Maybe we should ask the captain before autoadding them! buf = flute_room.buf util.flute_channel_msg(buf, "User '%s' (friend name: %s) was added to the flute room!" % \ (sender_nick, joining_friend_name), color="green") # We are captains in the channel. Act like it! # There is a new room member! Refresh and send new key! send_key_transport_packet(flute_room) return ""