def handle2(self): # print("Handle", self.client_address, "in child", os.getpid()) self.keyid, self.key = self.server.helper.get_server_key() s = self.server.wrapper.accept(self.request) if not s: return 'invalid_tls_failure' if not self.server.helper.allow_any_alpn: alpn_protocol = s.selected_alpn_protocol() if alpn_protocol not in [NTS_ALPN_PROTO]: return ('invalid_alpn_protocol') self.info.update(s.info()) if DEBUG >= 2: print("keyid = unhexlify('''%s''')" % hexlify(self.keyid)) print("server_key = unhexlify('''%s''')" % hexlify(self.key)) self.npn_protocols = [] self.aead_algorithms = [] self.eom_received = False self.errors = set() self.warnings = set() npn_ack = False aead_ack = False protocols = [] while True: resp = self.recv_all(s, 4) if resp is None: return 'invalid_premature_eof' return 1 if (len(resp) < 4): print("Premature end of client request", file=sys.stderr) return 'invalid_short_field' body_len = struct.unpack(">H", resp[2:4])[0] if body_len > 0: resp += self.recv_all(s, body_len) record = Record(resp) self.process_record(record) if record.rec_type == RT_END_OF_MESSAGE: break c2s_key = s.export_keying_material(self.server.key_label, NTS_TLS_Key_LEN, NTS_TLS_Key_C2S) s2c_key = s.export_keying_material(self.server.key_label, NTS_TLS_Key_LEN, NTS_TLS_Key_S2C) response = self.get_response(c2s_key, s2c_key) s.sendall(b''.join(map(bytes, response))) s.shutdown() return 'success'
def fix_bootloader(self, disable_bootloader=False): jump_to_main_prog = self._read_phy(0, 4) logger.debug('reset code before fix: ' + hexlify(jump_to_main_prog)) if not disable_bootloader: assert(self.BootStart & 1 == 0) k = self.BootStart >> 1 # http://ww1.microchip.com/downloads/en/DeviceDoc/39500a.pdf p.726 # GOTO k (2 words instruction) self._write_phy(0, encode_instruction('11101111abcdefgh', k & 0xff)) self._write_phy(2, encode_instruction('1111abcdefghijkl', k >> 8)) logger.debug('reset code after fix: ' + hexlify(self._read_phy(0, 4))) self._write_phy(self.BootStart - len(jump_to_main_prog), jump_to_main_prog)
def fix_bootloader(self, disable_bootloader=False): jump_to_main_prog = self._read_phy(0, 6) logger.debug('reset code before fix: ' + hexlify(jump_to_main_prog)) if not disable_bootloader: assert(self.BootStart & 1 == 0) # http://ww1.microchip.com/downloads/en/DeviceDoc/70157F.pdf p.250 # GOTO lit23 (2 words instruction) self._write_phy(0, encode_instruction('00000100abcdefghijklmnop', self.BootStart & 0xffff)) self._write_phy(3, encode_instruction('00000000000000000abcdefg', self.BootStart >> 16)) logger.debug('reset code after fix: ' + hexlify(self._read_phy(0, 6))) self._write_phy(self._pic24_addr_to_phy(self.BootStart) - len(jump_to_main_prog), jump_to_main_prog)
def pack(self): buf = super(NTSPacketHelper, self).pack() if self.enc_ext is not None: plaintext = b''.join([_.pack() for _ in self.enc_ext]) aead = self.get_aead() nonce = os.urandom(16) if 0: print("key %u %s" % (len(self.pack_key), binascii.hexlify(self.pack_key))) print("nonce %u %s" % (len(nonce), binascii.hexlify(nonce))) print("add %u %s" % (len(buf), binascii.hexlify(buf))) print("plain %u %s" % (len(plaintext), binascii.hexlify(plaintext))) ciphertext = bytes( aead.encrypt(self.pack_key, nonce, plaintext, buf)) if 0: print("cipher %u %s" % (len(ciphertext), binascii.hexlify(ciphertext))) if self.debug: print("key = unhexlify('''%s''')" % (hexlify(self.pack_key))) print("nonce = unhexlify('''%s''')" % hexlify(nonce)) print("ad = unhexlify('''%s''')" % hexlify(buf[:10])) print("ciphertext = unhexlify('''%s''')" % hexlify(ciphertext[:10])) print("plaintext = unhexlify('''%s''')" % hexlify(plaintext[:10])) # TODO maybe I should allow odd sized nonces and ciphertext if len(nonce) % 4 != 0: raise ValueError("nonce length is not a multiple of 4") if len(ciphertext) % 4 != 0: raise ValueError("ciphertext length is not a multiple of 4") a = [ struct.pack('>HH', len(nonce), len(ciphertext)), nonce, ciphertext, ] auth = NTPExtensionField(NTPExtensionFieldType.NTS_Authenticator, b''.join(a)) buf += auth.pack(last=True) return buf
def get(self): attrs = {} if 'proxy' in self.request.arguments: attrs.update( dict( incoming_proxy_ws = WebSocketIncomingProxyHandler.instances, incoming_tcp_listener = IncomingConnectionListenProxy.byport, udp_proxy = [[p, p.socks] for p in WebSocketUDPProxyHandler.instances], ws_proxy = WebSocketProxyHandler.instances, )) else: attrs.update( dict( clients = [ (c, dict( (hexlify(h), t) for h,t in c.torrents.iteritems() )) for c in Client.instances ], trackers = Tracker.instances, ws_prot = WebSocketProtocolHandler.instances, connections = Connection.instances, torrents = dict( (binascii.hexlify(h), {'torrent':t, 'conns':t.connections,'attrs':t._attributes}) for h,t in Torrent.instances.iteritems() ), peers = [dict( (str(k),v) for k,v in Peer.instances_compact.items() ), dict( (hexlify(k),v) for k,v in Peer.instances_peerid.items() )] ) ) def custom(obj): return escape(str(obj)) self.write('<html><body><pre>') self.write( json.dumps( attrs, indent=2, sort_keys = True, default=custom ) ) # options['colorize'].set(colorval) self.write('</pre><script src="/static/repl.js"></script>') self.write('<p><input style="width:100%" name="input" autocomplete="off" type="text" onkeydown="keydown(this, event);" /></p><div id="output" style="border:1px solid black; margin: 1em"></div>') command = """ Connection.initiate(host,port,startuphash) """ self.write('<pre>%s</pre>' % command) self.write('</body></html>')
def get(self): client = Client.instance() if 'list' in self.request.arguments: torrents = [] for h,t in client.torrents.iteritems(): hash = hexlify(h) r = [None for _ in range(len(TorrentDef.coldefs))] r[TorrentDef.coldefnames['hash']] = hash t_attrs = t.get_attributes() for key in t_attrs: if key in TorrentDef.coldefnames: r[TorrentDef.coldefnames[key]] = t_attrs[key] torrents.append(r) self.writeout(torrents) elif 'action' in self.request.arguments: action = self.get_argument('action') if action == 'getsettings': rows = [] rows.append(['bind_port', 0, options.port, {}]) ret = {'settings':rows} self.writeout(ret)
def get_attribute(self, key): if key == 'down_speed': return self.bitcounter.recent() elif key == 'progress': if self.bitmask: return (1000 * self.bitmask.count(1)) / len(self.bitmask) else: return 0 elif key == 'message': return '' elif key == 'status': return self._attributes[key] elif key == 'name': if self.meta: return self.meta['info']['name'] else: return hexlify(self.hash) elif key == 'size': return self.get_size() if self.meta else None elif key == 'downloaded': if self.bitmask: return self.bitmask.count(1) * self.get_piece_len() else: return 0 elif key == 'peers': return len(self.connections) else: logging.error('unsupported attribute %s' % key)
def get(self): client = Client.instance() if 'list' in self.request.arguments: torrents = [] for h, t in client.torrents.iteritems(): hash = hexlify(h) r = [None for _ in range(len(TorrentDef.coldefs))] r[TorrentDef.coldefnames['hash']] = hash t_attrs = t.get_attributes() for key in t_attrs: if key in TorrentDef.coldefnames: r[TorrentDef.coldefnames[key]] = t_attrs[key] torrents.append(r) self.writeout(torrents) elif 'action' in self.request.arguments: action = self.get_argument('action') if action == 'getsettings': rows = [] rows.append(['bind_port', 0, options.port, {}]) ret = {'settings': rows} self.writeout(ret)
def get(self): attrs = {} if 'proxy' in self.request.arguments: attrs.update( dict( incoming_proxy_ws=WebSocketIncomingProxyHandler.instances, incoming_tcp_listener=IncomingConnectionListenProxy.byport, udp_proxy=[[p, p.socks] for p in WebSocketUDPProxyHandler.instances], ws_proxy=WebSocketProxyHandler.instances, )) else: attrs.update( dict(clients=[(c, dict((hexlify(h), t) for h, t in c.torrents.iteritems())) for c in Client.instances], trackers=Tracker.instances, ws_prot=WebSocketProtocolHandler.instances, connections=Connection.instances, torrents=dict((binascii.hexlify(h), { 'torrent': t, 'conns': t.connections, 'attrs': t._attributes }) for h, t in Torrent.instances.iteritems()), peers=[ dict((str(k), v) for k, v in Peer.instances_compact.items()), dict((hexlify(k), v) for k, v in Peer.instances_peerid.items()) ])) def custom(obj): return escape(str(obj)) self.write('<html><body><pre>') self.write(json.dumps(attrs, indent=2, sort_keys=True, default=custom)) # options['colorize'].set(colorval) self.write('</pre><script src="/static/repl.js"></script>') self.write( '<p><input style="width:100%" name="input" autocomplete="off" type="text" onkeydown="keydown(this, event);" /></p><div id="output" style="border:1px solid black; margin: 1em"></div>' ) command = """ Connection.initiate(host,port,startuphash) """ self.write('<pre>%s</pre>' % command) self.write('</body></html>')
def from_buf(buf): """Construct a Command object from a bytestring buf""" self = Command() self.stx, self.cmd, self.addr, self.counter = \ struct.unpack(self._fmt, buf[:8]) if self.stx != STX: logger.error('missing stx: ' + hexlify(buf)) return self
def populate(self): self.state = {'btapp':{'add':{'torrent':"[nf](string)(string,string)"}}} if len(self.client.torrents) > 0: self.state['btapp']['torrent'] = {'all':{}} for hash,torrent in self.client.torrents.iteritems(): outhash = hexlify(hash) self.state['btapp']['torrent']['all'][outhash] = torrent.dump_state() return self.state
def dump_state(self): data = {'stop': "[nf]()", 'start': "[nf]()", 'remove': "[nf](number)()", 'recheck': "[nf]()", 'add_peer':"[nf](string)(dispatch)", 'hash':hexlify(self.hash), 'properties':{'all':self.get_attributes()}} if self.meta: data['file'] = self.dump_file_state() return data
def _request_summary(self): if self.request.connection.torrent and self.request.connection.torrent.hash: hashstr = '(' + hexlify(self.request.connection.torrent.hash)[:6] + '..)' else: hashstr = '--' if self.request.type == 'PIECE': otherinfo = str(len(self.request.payload)) else: otherinfo = str(self.request.args) return hashstr + ' ' + self.request.type + " " + otherinfo + ' ' +\ " (" + self.request.remote_ip + ")"
def fix_bootloader(self, disable_bootloader=False): boot_rom_first_instr, = struct.unpack('<L', self._read_phy(self.boot_rom_addr, 4)) logger.debug('first instruction on boot rom: 0x%08x' % boot_rom_first_instr) def jump_to(addr): return struct.pack('<4L', 0x3c1e0000 | (addr >> 16), # lui $30,[addr>>16] 0x37de0000 | (addr & 0xffff), # ori $30,$30,[addr&0xffff] 0x03c00008, # jr $30 0x70000000) # nop startprogram_routine = jump_to( self._phy_addr_to_pic32(self.boot_rom_addr + 0x50)) startprogram_routine_len = len(startprogram_routine) startprogram_routine_addr = self._pic32_addr_to_phy( self.BootStart - startprogram_routine_len) if boot_rom_first_instr in (0x27bdfffc, # addiu $sp,$sp,-4 0x70000000): # nop jump_bootstart_displ = 0x40 else: jump_bootstart_displ = 0 startprogram_routine = self._read_phy( self.boot_rom_addr, startprogram_routine_len) logger.debug('start program routine before fix: ' + hexlify(self._read_phy(startprogram_routine_addr, startprogram_routine_len))) logger.debug('start program routine after fix: ' + hexlify(startprogram_routine)) self._write_phy(startprogram_routine_addr, startprogram_routine) if not disable_bootloader: jump_bootstart_addr = self.boot_rom_addr + jump_bootstart_displ jump_bootstart_code = jump_to(self.BootStart) jump_bootstart_len = len(jump_bootstart_code) logger.debug('jump to bootstart before fix: ' + hexlify(self._read_phy(jump_bootstart_addr, jump_bootstart_len))) self._write_phy(jump_bootstart_addr, jump_bootstart_code) logger.debug('jump to bootstart after fix: ' + hexlify(jump_bootstart_code))
def compute_changes(self): add = {} remove = {} if len(self.client.torrents) > 0: if 'torrent' not in self.state['btapp']: self.state['btapp']['torrent'] = {'all': {}} for hash, torrent in self.client.torrents.iteritems(): outhash = hexlify(hash) if outhash not in self.state['btapp']['torrent']['all']: dump = torrent.dump_state() if 'btapp' in add: add['btapp']['torrent']['all'][outhash] = dump else: add['btapp'] = {'torrent': {'all': {outhash: dump}}} self.state['btapp']['torrent']['all'][outhash] = dump else: a, r = torrent.update_attributes( self.state['btapp']['torrent']['all'][outhash]) if a: if 'btapp' not in add: add['btapp'] = {'torrent': {'all': {}}} add['btapp']['torrent']['all'][outhash] = a if r: if 'btapp' not in remove: remove['btapp'] = {'torrent': {'all': {}}} remove['btapp']['torrent']['all'][outhash] = r toremove = [] for outhash in self.state['btapp']['torrent']['all']: hash = binascii.unhexlify(outhash) if hash not in self.client.torrents: logging.info('hash not found in cur torrents') if 'btapp' not in remove: remove['btapp'] = {'torrent': {'all': {}}} # torrent was removed remove['btapp']['torrent']['all'][outhash] = self.state[ 'btapp']['torrent']['all'][outhash] toremove.append(outhash) for outhash in toremove: del self.state['btapp']['torrent']['all'][outhash] return add, remove
def _request_summary(self): if self.request.connection.torrent and self.request.connection.torrent.hash: hashstr = '(' + hexlify( self.request.connection.torrent.hash)[:6] + '..)' else: hashstr = '--' if self.request.type == 'PIECE': otherinfo = str(len(self.request.payload)) else: otherinfo = str(self.request.args) return hashstr + ' ' + self.request.type + " " + otherinfo + ' ' +\ " (" + self.request.remote_ip + ")"
def fix_bootloader(self, disable_bootloader=False): """Fix the first block to point the reset address to the bootloader. Put in the location expected by the bootloader a small ARM-Thumb program to initialize the stack pointer and to jump to the program being written.""" reset_vec = self._read_phy(0, 8) stackp, resetaddr = struct.unpack('<LL', reset_vec) logger.debug('reset vector before fix: ' + hexlify(reset_vec)) if resetaddr & 1 != 1: logger.warn('reset address 0x%x does not have a Thumb mark -- enforcing it' % resetaddr) resetaddr |= 1 # Change the reset address to point to the bootloader code. if not disable_bootloader: self._write_phy(4, struct.pack('<L', self.BootStart|1)) logger.debug('reset vector after fix: ' + hexlify(self._read_phy(0, 8))) def load_r0(value): """Return ARM-Thumb instructions for loading a 32-bit value into the r0 register.""" return b''.join([ # movw r0, #lo encode_instruction('0fgh0000ijklmnop11110e100100abcd', value & 0xffff), # movt r0, #hi encode_instruction('0fgh0000ijklmnop11110e101100abcd', (value >> 16) & 0xffff), ]) program = b''.join([ load_r0(stackp), encode_instruction('0100011010000101'), # mov sp, r0 load_r0(resetaddr), encode_instruction('0100011100000000'), # bx r0 ]) assert(len(program) == 20) # length expected by bootloader logger.debug('start program routine: ' + hexlify(program)) self._write_phy(self.BootStart - len(program), program)
def dump_state(self): data = { 'stop': "[nf]()", 'start': "[nf]()", 'remove': "[nf](number)()", 'recheck': "[nf]()", 'add_peer': "[nf](string)(dispatch)", 'hash': hexlify(self.hash), 'properties': { 'all': self.get_attributes() } } if self.meta: data['file'] = self.dump_file_state() return data
def compute_changes(self): add = {} remove = {} if len(self.client.torrents) > 0: if 'torrent' not in self.state['btapp']: self.state['btapp']['torrent'] = {'all':{}} for hash, torrent in self.client.torrents.iteritems(): outhash = hexlify(hash) if outhash not in self.state['btapp']['torrent']['all']: dump = torrent.dump_state() if 'btapp' in add: add['btapp']['torrent']['all'][outhash] = dump else: add['btapp'] = {'torrent':{'all':{outhash:dump}}} self.state['btapp']['torrent']['all'][outhash] = dump else: a, r = torrent.update_attributes(self.state['btapp']['torrent']['all'][outhash]) if a: if 'btapp' not in add: add['btapp'] = {'torrent':{'all':{}}} add['btapp']['torrent']['all'][outhash] = a if r: if 'btapp' not in remove: remove['btapp'] = {'torrent':{'all':{}}} remove['btapp']['torrent']['all'][outhash] = r toremove = [] for outhash in self.state['btapp']['torrent']['all']: hash = binascii.unhexlify(outhash) if hash not in self.client.torrents: logging.info('hash not found in cur torrents') if 'btapp' not in remove: remove['btapp'] = {'torrent':{'all':{}}} # torrent was removed remove['btapp']['torrent']['all'][outhash] = self.state['btapp']['torrent']['all'][outhash] toremove.append(outhash) for outhash in toremove: del self.state['btapp']['torrent']['all'][outhash] return add, remove
def populate(self): self.state = { 'btapp': { 'add': { 'torrent': "[nf](string)(string,string)" } } } if len(self.client.torrents) > 0: self.state['btapp']['torrent'] = {'all': {}} for hash, torrent in self.client.torrents.iteritems(): outhash = hexlify(hash) self.state['btapp']['torrent']['all'][ outhash] = torrent.dump_state() return self.state
def recv_data(self): """Receive data (mainly for getting the BootInfo struct)""" data = self.f.read(HID_buf_size) logger.debug('recv data: ' + hexlify(data)) return data
def send_data(self, data): """Send data (mainly for writing the flash)""" logger.debug('send data: ' + hexlify(data)) self.f.write(b'\x00' + data.ljust(HID_buf_size, b'\xff'))
def __repr__(self): return '<Torrent %s (meta:%s, %s)>' % (hexlify(self.hash), True if self.meta else False, self.get_summary())
def __repr__(self): return '<Torrent %s (meta:%s, %s)>' % (hexlify( self.hash), True if self.meta else False, self.get_summary())
def get_response(self, c2s_key, s2c_key): protocols = [] if not self.npn_protocols: self.error(ERR_BAD_REQUEST, "No NPN record received") elif not flatten(self.npn_protocols): pass else: for protocol in flatten(self.npn_protocols): if protocol in SUPPORTED_PROTOCOLS: protocols.append(protocol) else: self.notice("Unknown NPN %u" % protocol) if not protocols: self.error(ERR_BAD_REQUEST, "No supported NPN received") algorithms = [] if not self.aead_algorithms: self.error(ERR_BAD_REQUEST, "No AEAD record received") elif not flatten(self.aead_algorithms): pass else: for algorithm in flatten(self.aead_algorithms): if algorithm in SUPPORTED_ALGORITHMS: algorithms.append(algorithm) else: self.notice("Unknown AEAD algorithm %u" % algorithm) if not algorithms: self.error(ERR_BAD_REQUEST, "No supported AEAD algorithms received") if not self.eom_received: self.error(ERR_BAD_REQUEST, "No EOM record received") records = [] for code in sorted(self.errors): records.append(Record.make(True, RT_ERROR, struct.pack(">H", code))) for code in sorted(self.warnings): records.append( Record.make(True, RT_WARNING, struct.pack(">H", code))) if protocols: records.append( Record.make(True, RT_NEXT_PROTO_NEG, struct.pack('>H', protocols[0]))) else: records.append(Record.make(True, RT_NEXT_PROTO_NEG, b'')) if algorithms: aead_algo = algorithms[0] records.append( Record.make(True, RT_AEAD_NEG, struct.pack('>H', aead_algo))) else: records.append(Record.make(True, RT_AEAD_NEG, b'')) if self.errors: records.append(Record.make(True, RT_END_OF_MESSAGE)) return records if DEBUG >= 2: print("c2s_key = unhexlify('''%s''')" % hexlify(c2s_key)) print("s2c_key = unhexlify('''%s''')" % hexlify(s2c_key)) if self.server.ntpv4_server is not None: records.append( Record.make(True, RT_NTPV4_SERVER, self.server.ntpv4_server)) if self.server.ntpv4_port is not None: records.append( Record.make(True, RT_NTPV4_PORT, struct.pack(">H", self.server.ntpv4_port))) for i in range(8): cookie = NTSCookie().pack(self.keyid, self.key, aead_algo, s2c_key, c2s_key) records.append(Record.make(False, RT_NEW_COOKIE, cookie)) records.append(Record.make(True, RT_END_OF_MESSAGE)) return records