예제 #1
0
 def sendall(self, x):
     try:
         msgid, tp, dat0 = x.split(b'\0', 2)
         if msgid in known_pkts: return
         known_pkts.add(msgid)
         if tp == b'eMSG':
             tgt, dat = dat0.split(b'\0', 1)
             if tgt == bot_hash.encode('ascii'):
                 dat2 = cryptutil.decrypt(dat, bot_key, 'd')
                 sndr, tp2, dat3 = dat2.split(b'\0', 2)
                 if tp2 == b'MSG':
                     msgid2, rec, sndr2, tp3, dat4 = dat3.split(b'\0', 4)
                     if tp3 == b'KEY':
                         key = cryptutil.import_binary_key(dat4[:-128])
                         known_keys[cryptutil.hash(key)] = key
                 sndr1 = sndr.decode('ascii', 'replace')
                 if sndr1 in known_keys:
                     if not cryptutil.check_sign(dat2, known_keys[sndr1]): print('Badly signed!')
                     if tp2 == b'MSG':
                         if msgid2 in known_msgs: return
                         known_msgs.add(msgid2)
                         if tp3 == b'RELAY':
                             msg2 = dat4[:-128].split(b'\0', 2)[2]
                             if msg2.startswith(b'eMSG\0'):
                                 msg2 = b'EMSG\0'+msg2.split(b'\0', 2)[2]
                             msg2 = msgid2+b'\0'+msg2
                             self.queue.put(msg2)
                         self.send_encrypted_back(sndr, b'ACK\0'+bot_hash.encode('ascii')+b'\0'+sndr+b'\0'+msgid2)
                 else: self.queue.put(os.urandom(8).hex().encode('ascii')+b'\0MSG\0'+os.urandom(8).hex().encode('ascii')+b'\0'+sndr+b'\0'+bot_hash.encode('ascii')+b'\0NEEDKEY\0')
     except Exception:
         import traceback
         traceback.print_exc()
예제 #2
0
def import_contact(c, interactive=True):
    try:
        if isinstance(c, bytes):
            c = json.loads(c.decode('utf-8'))
        if interactive:
            print('Import this contact?')
            print('Peers:')
            for k, v in c['peers'].items():
                print('*',
                      format_nickname(cryptutil.hash(cryptutil.import_key(k))))
                if v != None:
                    print('      (@%s)' % v)
                if k in c['trusted']:
                    print('      (trusted)')
            print('Sockets:')
            for x in c['sockets']:
                print('*', x)
            print('Relays:')
            for k, v in c['relays'].items():
                print('* %s via %s' % (format_nickname(k), format_nickname(v)))
            print('Exclusive routes:')
            for k, v in c['exclusive'].items():
                print('* %s excl. via %s' % (format_nickname(k), v))
            try:
                input('Press Enter to continue, Ctrl+C to abort')
            except KeyboardInterrupt:
                return
        for k, v in c['peers'].items():
            config['peers'][cryptutil.hash(cryptutil.import_key(k))] = k
            if v != None:
                config['nicknames'][cryptutil.hash(
                    cryptutil.import_key(k))] = v
            if cryptutil.hash(cryptutil.import_key(k)) in c['trusted']:
                config['trusted'].append(
                    cryptutil.hash(cryptutil.import_key(k)))
        for x in c['sockets']:
            if x not in config['sockets']:
                start_peer_socket(x)
                config['sockets'].append(x)
        config['relays'].update(c['relays'])
        config['exclusive'].update(c['exclusive'])
        update_config()
    except:
        print('Error during contact import:', file=sys.stderr)
        sys.excepthook(*sys.exc_info())
예제 #3
0
def handle_incoming(pktid, idx, dat, flags, verified_as, rec):
    if not (flags & F_FORWARDED):
        if idx in msg_cache: return
        msg_cache.add(idx)
    frontend.event('msg_pkt_id', idx.decode('ascii', 'replace'),
                   pktid.decode('ascii', 'replace'))
    #   print(dat)
    snd0, tp, dat = dat.split(b'\0', 2)
    snd = snd0.decode('ascii', 'replace')
    if not (flags & F_VERIFIED) and snd in config['peers']:
        frontend.warn('Warning: message %s not verified, may be spoofed' %
                      idx.decode('ascii', 'replace'))
    elif (flags & F_VERIFIED) and snd != verified_as:
        frontend.warn('Warning: message %s: sender spoofed, dropping' %
                      idx.decode('ascii', 'replace'))
        return
    if rec != self.encode('ascii'):
        frontend.event('originally_written', idx.decode('ascii', 'replace'),
                       format_nickname(rec.decode('ascii', 'replace')))


#   print('message:', snd0, tp, dat)
    if tp == b'NEEDKEY':
        send_key_to(snd)
        return
    if tp == b'MSG':
        frontend.event('incoming_msg', idx.decode('ascii', 'replace'),
                       format_nickname(snd), dat)
    elif tp == b'KEY':
        key = cryptutil.import_binary_key(dat)
        config['peers'][cryptutil.hash(key)] = cryptutil.export_key(key)
    elif tp == b'RELAY':
        tgt, relayed, msg = dat.split(b'\0', 2)
        tgt = tgt.decode('ascii', 'replace')
        if snd in config['trusted'] and not (
                flags & F_FORWARDED) or tgt in config['exclusive'] and config[
                    'exclusive'][tgt].startswith('python://'):
            send_msg(tgt,
                     b'RELAYED\0' + msg,
                     relay_idx=float('inf') if relayed == b'0' else 0)
        else:
            frontend.warn('Warning: RELAY message from an untrusted source')
    elif tp == b'RELAYED':
        handle_packet(idx + b'\0' + dat, F_RELAYED)
    elif tp == b'FORWARD':
        frontend.event('was_forwarded', idx.decode('ascii', 'replace'),
                       format_nickname(snd0.decode('ascii', 'replace')))
        handle_packet(idx + b'\0' + dat, F_FORWARDED)
    elif tp == b'CONTACT':
        saved_contacts[idx.decode('ascii', 'replace')] = dat
        frontend.event('incoming_contact', idx.decode('ascii', 'replace'),
                       format_nickname(snd0.decode('ascii', 'replace')))
    else:
        frontend.warn('Warning: dropping unknown message type: %r' % tp)
예제 #4
0
BOT_KEY = 'MIICXAIBAAKBgQDDSRdeGz7KsA+KYbP9e/T741RWphm8gEH1CAulYQULItkrHPy51kufXdmK+j7ToTzOCUOHhBcSBqOgLsH/bpL9K7HY9WIlUjn0D522Sl1Jn6uSTrO3nWGBioPqRFPlxERZIKEj5A+tLS2Rlge9hLHUes3SRpx0vVb/VpEJlKGwAQIDAQABAoGAE6WrYa7pCthav+fjhWmutJbi+dK9PR9EQ4Q7M7jGmp+3bKR+cq3yLsbw55AUuRL8PJhnAF/UOF6NoMSDhRDZXc034++ZfFrNbCitZuDIl4/f0Ue7jpDec00ob8V/qsWDeBuy7/QL/Xdk3gwahx/SpUp5ma1rcj7SQEDKrGJrwAkCQQDU+cWP0ZCP3Y8xdSVYieEBA2mgpyaYH46KSqf1wdQUIWV0UyAnj1L0lq0Mv6PV7EzU8ZOPwwPRRI+p8nHM1T79AkEA6rx1BoCHPI4rrE2pkpYlpWDjN897PfFvyKd9NWnkmpkdScMlpsy+BzCMopLtxrKKG9F79jB7m72tCY17r6S+VQJAMFKz5tvv5xSoZtpjrOEr8mTp1I/Yi++tEee6kGJ4UlD5ihlKVG+KrQB7J0dcTy+chzyA9L+U4CikSDVAaO+BqQJBALm6LyXb4CTroGaOdFNFdbfqdx2bjrmuJHIxA4KVrIkeCOxp+YqGiPyLT1r6wiPq9BeaomhiaAsMArOCPJD22pkCQAWB6kQFWXRWwztpFeKR2i6gal7xKT9iFwuho5dKL+7pNOJb46hxG6zcf3hzgUgK/goU7Gn7f8nz75MxTPgWSEk='

import cryptutil, queue, os

bot_key = cryptutil.import_key(BOT_KEY)
bot_hash = cryptutil.hash(bot_key.publickey())

known_keys = {}
known_pkts = set()
known_msgs = set()

class TheSocket:
    def __init__(self):
        self.queue = queue.Queue()
    def recv(self, x):
        return self.queue.get()
    def send_encrypted_back(self, sndr, x):
        sndr1 = sndr.decode('ascii', 'replace')
        self.queue.put(os.urandom(8).hex().encode('ascii')+b'\0eMSG\0'+sndr+b'\0'+cryptutil.encrypt(cryptutil.sign(bot_hash.encode('ascii')+b'\0'+x, bot_key), known_keys[sndr1], 'e'))
    def sendall(self, x):
        try:
            msgid, tp, dat0 = x.split(b'\0', 2)
            if msgid in known_pkts: return
            known_pkts.add(msgid)
            if tp == b'eMSG':
                tgt, dat = dat0.split(b'\0', 1)
                if tgt == bot_hash.encode('ascii'):
                    dat2 = cryptutil.decrypt(dat, bot_key, 'd')
                    sndr, tp2, dat3 = dat2.split(b'\0', 2)
                    if tp2 == b'MSG':
                        msgid2, rec, sndr2, tp3, dat4 = dat3.split(b'\0', 4)
예제 #5
0
import json, sys, cryptutil, base64

data = open(sys.argv[1]).read().split('\n')

assert data[0].startswith('BOT_KEY = ')
bot_key = eval(data[0][10:])
bot_id = cryptutil.hash(cryptutil.import_key(bot_key).publickey())

if '--devel' in sys.argv:
    path = repr(os.path.abspath(sys.argv[1]))
    data = ('exec(compile(open(' + path + ', "rb").read(), ' + path +
            ', "exec"))').encode('utf-8')
else:
    data = open(sys.argv[1], 'rb').read()

sock = 'python://' + ''.join(base64.b64encode(data).decode('ascii').split())

print(
    json.dumps({
        'peers': {
            cryptutil.export_key(cryptutil.import_key(bot_key).publickey()):
            sys.argv[2]
        },
        'trusted': [bot_id],
        'sockets': [sock],
        'relays': {},
        'exclusive': {
            bot_id: sock
        }
    }))
예제 #6
0
def handle_packet(msg, flags=0, verified_as=None, sender=None):
    if flags & F_FORWARDED: flags |= F_RELAYED
    idx, tp, dat = msg.split(b'\0', 2)
    if idx in pkt_cache: return
    pkt_cache.add(idx)
    #   print('[relayed=%r][verified=%r][forwarded=%r] %r'%(bool(flags&F_RELAYED), bool(flags&F_VERIFIED), bool(flags&F_FORWARDED), msg))
    if tp == b'EMSG':
        #       if not (flags & F_EMSG_NOFORWARD): print('true EMSG! hi anonymity!')
        dat0 = cryptutil.decrypt(dat, privkey, 'd')
        if flags & F_EMSG_NOFORWARD: flags &= ~F_EMSG_NOFORWARD
        else: send_pkt(msg)
        if dat0 == None:
            return  #not for our eyes
        snd, dat = dat0[:-128].split(b'\0', 1)
        snd = snd.decode('ascii', 'replace')
        if snd not in config['peers']:
            tp0, dat0 = dat.split(b'\0', 1)
            if tp0 == b'MSG':
                idx1, rec1, snd1, tp1, dat1 = dat0.split(b'\0', 4)
                if tp1 == b'KEY':
                    #                   print('key is:', dat1)
                    key = cryptutil.import_binary_key(dat1)
                    #                   print('from %r: got key of %r'%(snd, cryptutil.hash(key)))
                    config['peers'][cryptutil.hash(
                        key)] = cryptutil.export_key(key)
                    update_config()
            elif tp0 == b'ACK':
                return
            if snd not in config['peers']:
                send_msg(snd, b'NEEDKEY\0')
                return
        if not cryptutil.check_sign(
                dat0, cryptutil.import_key(config['peers'][snd])):
            frontend.warn('Warning: invalid EMSG signature')
            return
        else:
            pkt_cache.remove(idx)
            msgid = handle_packet(idx + b'\0' + dat,
                                  flags | F_VERIFIED | F_ENCRYPTED, snd,
                                  sender)
            if msgid != None:
                saved_msgs[msgid.decode('ascii',
                                        'replace')] = b'SIGNED\0' + dat0
            return msgid
    if tp == b'eMSG':
        rec, dat0 = dat.split(b'\0', 1)
        if rec != self.encode('ascii'):
            send_pkt(msg, rec.decode('ascii', 'replace'))
            return
        else:
            pkt_cache.remove(idx)
            return handle_packet(idx + b'\0EMSG\0' + dat0,
                                 flags | F_EMSG_NOFORWARD, verified_as, sender)
    if tp == b'SIGNED':
        dat0 = dat
        snd, dat = dat0[:-128].split(b'\0', 1)
        snd = snd.decode('ascii', 'replace')
        if snd not in config['peers']:
            frontend.warn(
                'Warning: could not validate SIGNED message, no public key available'
            )
        elif not cryptutil.check_sign(
                dat0, cryptutil.import_key(config['peers'][snd])):
            frontend.warn('Warning: dropping incorrectly SIGNED message')
            return
        pkt_cache.remove(idx)
        return handle_packet(idx + b'\0' + dat, flags | F_VERIFIED, snd,
                             sender)
    if tp == b'MSG' and not (flags & F_RELAYED):
        idx2, rec, dat0 = dat.split(b'\0', 2)
        if rec == self.encode('ascii'):
            handle_send_ack(idx2, dat0)
    if tp == b'MSG':
        idx2, rec, dat = dat.split(b'\0', 2)
        if rec == self.encode('ascii') or (flags & F_FORWARDED):
            handle_incoming(idx, idx2, dat, flags, verified_as, rec)
            saved_msgs[idx2.decode('ascii', 'replace')] = msg.split(b'\0',
                                                                    1)[1]
            return idx2
        else:
            send_pkt(msg, rec)
    elif tp == b'ACK':
        snd, rec, idx2 = dat.split(b'\0', 2)
        if rec == self.encode('ascii'):
            try:
                del sender_pool[idx2.decode('ascii', 'replace')]
            except KeyError:
                pass
            else:
                rs[snd].recalc(sender)
            frontend.event('delivered', idx2.decode('ascii', 'replace'))
        else:
            send_pkt(msg, rec)
    else:
        frontend.warn('Warning: dropping unrecognized packet: %r' % msg)
예제 #7
0
def unimport_contact(c, interactive=True):
    try:
        if isinstance(c, bytes):
            c = json.loads(c.decode('utf-8'))
        if interactive:
            print('Unimport this contact?')
            print('Peers:')
            for k, v in c['peers'].items():
                print('*',
                      format_nickname(cryptutil.hash(cryptutil.import_key(k))))
                if v != None:
                    print('      (@%s)' % v)
                if k in c['trusted']:
                    print('      (trusted)')
            print('Sockets:')
            for x in c['sockets']:
                print('*', x)
            print('Relays:')
            for k, v in c['relays'].items():
                print('* %s via %s' % (format_nickname(k), format_nickname(v)))
            print('Exclusive routes:')
            for k, v in c['exclusive'].items():
                print('* %s excl. via %s' % (format_nickname(k), v))
            try:
                input('Press Enter to continue, Ctrl+C to abort')
            except KeyboardInterrupt:
                return
        for k, v in c['peers'].items():
            try:
                del config['peers'][cryptutil.hash(cryptutil.import_key(k))]
            except KeyError:
                frontend.warn('Warning: %s was not in your contacts' %
                              cryptutil.hash(cryptutil.import_key(k)))
            if v != None:
                try:
                    del config['nicknames'][cryptutil.hash(
                        cryptutil.import_key(k))]
                except KeyError:
                    frontend.warn('Warning: @%s was not in your contacts' % v)
            if cryptutil.hash(cryptutil.import_key(k)) in c['trusted']:
                try:
                    config['trusted'].remove(
                        cryptutil.hash(cryptutil.import_key(k)))
                except ValueError:
                    frontend.warn('Warning: %s was not in your trust list' %
                                  cryptutil.hash(cryptutil.import_key(k)))
        for x in c['sockets']:
            if x in config['sockets']:
                #               start_peer_socket(x)
                try:
                    config['sockets'].remove(x)
                except ValueError:
                    frontend.warn(
                        'Warning: socket %s was not in your socket list' % x)
                else:
                    frontend.warn(
                        'Note: socket %s removed from your socket list, will be disconnected on client restart'
                        % x)
        for r in c['relays']:
            try:
                del config['relays'][r]
            except ValueError:
                frontend.warn('Warning: no relay was configured for %s' % r)
        for r in c['exclusive']:
            try:
                del config['exclusive'][r]
            except ValueError:
                frontend.warn(
                    'Warning: no exclusive socket was configured for %s' % r)
        update_config()
    except:
        print('Error during contact unimport:', file=sys.stderr)
        sys.excepthook(*sys.exc_info())
예제 #8
0
                    pass
                x[0] = socketutil.create_socket(addr)

    def receiver_thread():
        while True:
            try:
                msgq.put((x[0].recv(1048576), q))
            except:
                pass

    threading.Thread(target=sender_thread, daemon=True).start()
    threading.Thread(target=receiver_thread, daemon=True).start()


pkt_cache = set()
self = cryptutil.hash(pubkey)
if self not in config['peers']:
    config['peers'][self] = cryptutil.export_key(pubkey)
    update_config()
frontend.event('i_am', self)

saved_msgs = dbhelper.DBDict('msgs', binary=True)
saved_contacts = dbhelper.DBDict('contacts', binary=True)


def receiver_loop():
    while True:
        msg, snd = msgq.get()
        try:
            handle_packet(msg, sender=snd)
        except: