Пример #1
0
 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()
Пример #2
0
 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
Пример #3
0
 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
Пример #4
0
    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])
Пример #5
0
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 ""
Пример #6
0
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 ""
Пример #7
0
    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
Пример #8
0
 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))
Пример #9
0
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 ""
Пример #10
0
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 ""