<s> import dnslib . server <EOL> import dnslib <EOL> import time <EOL> import binascii <EOL> import os <EOL> import cryptocore <EOL> import sys <EOL> import json <EOL> import pwd <EOL> import grp <EOL> ch_A = ord ( "<STR_LIT:A>" ) <EOL> ch_Z = ord ( "<STR_LIT>" ) <EOL> ch_a = ord ( "<STR_LIT:a>" ) <EOL> ch_z = ord ( "<STR_LIT:z>" ) <EOL> ch_ZERO = ord ( "<STR_LIT:0>" ) <EOL> ch_FIVE = ord ( "<STR_LIT:5>" ) <EOL> ir1 = lambda c : c <= ch_Z and c >= ch_A <EOL> ir2 = lambda c : c <= ch_z and c >= ch_a <EOL> ir3 = lambda c : c <= ch_FIVE and c >= ch_ZERO <EOL> BASE32_SRC = b"<STR_LIT>" <EOL> def notsecure32_decode ( src ) : <EOL> ret = [ ] <EOL> bits = <NUM_LIT:0> <EOL> op = <NUM_LIT:0> <EOL> for char in ( ord ( s ) for s in src ) : <EOL> if ir1 ( char ) : <EOL> char -= ch_A <EOL> elif ir2 ( char ) : <EOL> char -= ch_a <EOL> elif ir3 ( char ) : <EOL> char = ( char - ch_ZERO + <NUM_LIT> ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> op = ( op | ( char << bits ) ) % <NUM_LIT> ; <EOL> bits += <NUM_LIT:5> ; <EOL> if bits >= <NUM_LIT:8> : <EOL> bits -= <NUM_LIT:8> <EOL> ret . append ( op ) <EOL> op = ( char >> ( <NUM_LIT:5> - bits ) ) % <NUM_LIT> ; <EOL> return bytes ( ret ) <EOL> def notsecure32_encode ( src ) : <EOL> sl = len ( src ) <EOL> ret = [ ] <EOL> bits = <NUM_LIT:0> <EOL> i = <NUM_LIT:0> <EOL> while ( i < sl ) : <EOL> c1 = src [ i ] <EOL> try : <EOL> c2 = src [ i + <NUM_LIT:1> ] <EOL> except IndexError : <EOL> c2 = <NUM_LIT:0> <EOL> a = BASE32_SRC [ ( ( c1 >> bits ) | ( c2 << ( <NUM_LIT:8> - bits ) ) ) & <NUM_LIT> ] <EOL> ret . append ( a ) <EOL> bits += <NUM_LIT:5> <EOL> if bits >= <NUM_LIT:8> : <EOL> bits -= <NUM_LIT:8> <EOL> i += <NUM_LIT:1> <EOL> return bytes ( ret ) <EOL> class ToxResolver ( dnslib . server . BaseResolver ) : <EOL> def __init__ ( self , cryptocore , cfg ) : <EOL> self . home = cfg [ "<STR_LIT>" ] . encode ( "<STR_LIT:utf8>" ) <EOL> self . cryptocore = cryptocore <EOL> self . ttl = cfg [ "<STR_LIT>" ] <EOL> with open ( "<STR_LIT>" , "<STR_LIT:r>" ) as namelist_f : <EOL> self . names = json . load ( namelist_f ) <EOL> self . workable_domains = set ( k . split ( "<STR_LIT:@>" ) [ <NUM_LIT:1> ] for k in self . names ) <EOL> def resolve ( self , request , handler ) : <EOL> question = request . get_q ( ) <EOL> req_name = str ( question . get_qname ( ) ) <EOL> reply = request . reply ( ) <EOL> pivot = req_name . rfind ( "<STR_LIT>" ) <EOL> if pivot == - <NUM_LIT:1> : <EOL> reply . header . rcode = dnslib . RCODE . NXDOMAIN <EOL> return reply <EOL> name = req_name [ : pivot ] . rstrip ( "<STR_LIT:.>" ) <EOL> suffix = req_name [ pivot : ] <EOL> domain = suffix [ <NUM_LIT:5> : ] . rstrip ( "<STR_LIT:.>" ) <EOL> if question . qtype == <NUM_LIT:16> : <EOL> if not name and domain in self . workable_domains : <EOL> reply . add_answer ( dnslib . RR ( req_name , <NUM_LIT:16> , ttl = <NUM_LIT:0> , <EOL> rdata = dnslib . TXT ( self . cryptocore . public_key . encode ( "<STR_LIT:ascii>" ) ) ) ) <EOL> return reply <EOL> first_try = self . try_tox3_resolve ( reply , name , domain , req_name ) <EOL> if not first_try : <EOL> return self . try_tox1_resolve ( reply , name , domain , req_name ) <EOL> else : <EOL> return first_try <EOL> elif question . qtype == <NUM_LIT:2> : <EOL> reply . add_answer ( dnslib . RR ( req_name , <NUM_LIT:2> , ttl = <NUM_LIT> , <EOL> rdata = dnslib . NS ( self . home ) <EOL> ) ) <EOL> return reply <EOL> else : <EOL> reply . header . rcode = dnslib . RCODE . NXDOMAIN <EOL> return reply <EOL> return reply <EOL> def try_tox3_resolve ( self , reply , name , domain , req_name ) : <EOL> if not name . startswith ( "<STR_LIT:_>" ) : <EOL> return None <EOL> encrypted = name . replace ( "<STR_LIT:.>" , "<STR_LIT>" ) [ <NUM_LIT:1> : ] <EOL> try : <EOL> b = notsecure32_decode ( encrypted ) <EOL> nonce = b [ : <NUM_LIT:4> ] + ( b"<STR_LIT>" * <NUM_LIT:20> ) <EOL> ck = b [ <NUM_LIT:4> : <NUM_LIT> ] <EOL> payload = b [ <NUM_LIT> : ] <EOL> dec_name = self . cryptocore . dsrep_decode_name ( ck , nonce , payload ) <EOL> except Exception : <EOL> return None <EOL> try : <EOL> dec_name = dec_name . decode ( "<STR_LIT:utf8>" ) <EOL> except UnicodeDecodeError : <EOL> return None <EOL> toxid = self . names . get ( "<STR_LIT>" . format ( dec_name , domain ) ) <EOL> if not toxid : <EOL> return None <EOL> msg = binascii . unhexlify ( toxid ) <EOL> nonce_reply = b [ : <NUM_LIT:4> ] + b"<STR_LIT>" + ( b"<STR_LIT>" * <NUM_LIT> ) <EOL> ct = self . cryptocore . dsrec_encrypt_key ( ck , nonce_reply , msg ) <EOL> key_part = notsecure32_encode ( ct ) . decode ( "<STR_LIT:ascii>" ) <EOL> base = "<STR_LIT>" . format ( key_part ) . encode ( "<STR_LIT:utf8>" ) <EOL> reply . add_answer ( dnslib . RR ( req_name , <NUM_LIT:16> , ttl = <NUM_LIT:0> , <EOL> rdata = dnslib . TXT ( base ) ) ) <EOL> return reply <EOL> def try_tox1_resolve ( self , reply , name , domain , req_name ) : <EOL> toxid = self . names . get ( "<STR_LIT>" . format ( name , domain ) ) <EOL> if not toxid : <EOL> reply . header . rcode = dnslib . RCODE . NXDOMAIN <EOL> return reply <EOL> else : <EOL> rec = "<STR_LIT>" . format ( toxid ) . encode ( "<STR_LIT:utf8>" ) <EOL> reply . add_answer ( dnslib . RR ( req_name , <NUM_LIT:16> , ttl = self . ttl , <EOL> rdata = dnslib . TXT ( rec ) ) ) <EOL> return reply <EOL> def make_server ( cryptocore , cfg ) : <EOL> return dnslib . server . DNSServer ( ToxResolver ( cryptocore , cfg ) , <EOL> port = cfg [ "<STR_LIT>" ] , <EOL> address = cfg [ "<STR_LIT>" ] , <EOL> logger = None , <EOL> tcp = False ) <EOL> def main ( ) : <EOL> with open ( "<STR_LIT>" , "<STR_LIT:r>" ) as config_file : <EOL> cfg = json . load ( config_file ) <EOL> cc = cryptocore . CryptoCore ( ) <EOL> print ( "<STR_LIT>" ) <EOL> print ( "<STR_LIT>" . format ( cc . public_key ) ) <EOL> if "<STR_LIT>" in cfg : <EOL> with open ( cfg [ "<STR_LIT>" ] , "<STR_LIT:w>" ) as pid : <EOL> pid . write ( str ( os . getpid ( ) ) ) <EOL> try : <EOL> server = make_server ( cc , cfg ) <EOL> if "<STR_LIT>" in cfg : <EOL> print ( "<STR_LIT>" ) <EOL> if os . getuid ( ) == <NUM_LIT:0> : <EOL> if "<STR_LIT::>" not in cfg [ "<STR_LIT>" ] : <EOL> user = cfg [ "<STR_LIT>" ] <EOL> group = None <EOL> else : <EOL> user , group = cfg [ "<STR_LIT>" ] . split ( "<STR_LIT::>" , <NUM_LIT:1> ) <EOL> uid = pwd . getpwnam ( user ) . pw_uid <EOL> if group : <EOL> gid = grp . getgrnam ( group ) . gr_gid <EOL> else : <EOL> gid = pwd . getpwnam ( user ) . pw_gid <EOL> os . setgid ( gid ) <EOL> os . setuid ( uid ) <EOL> else : <EOL> print ( "<STR_LIT>" ) <EOL> sys . exit ( ) <EOL> server . start ( ) <EOL> finally : <EOL> os . remove ( cfg [ "<STR_LIT>" ] ) <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> main ( ) </s>
