Exemplo n.º 1
0
    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'
Exemplo n.º 2
0
 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)
Exemplo n.º 3
0
 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)
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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>')
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
 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)
Exemplo n.º 8
0
 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)
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
    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>')
Exemplo n.º 11
0
 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
Exemplo n.º 12
0
 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
Exemplo n.º 13
0
    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
Exemplo n.º 14
0
 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
Exemplo n.º 15
0
    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 + ")"
Exemplo n.º 16
0
 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))
Exemplo n.º 17
0
    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
Exemplo n.º 18
0
    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 + ")"
Exemplo n.º 19
0
    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)
Exemplo n.º 20
0
 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
Exemplo n.º 21
0
    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
Exemplo n.º 22
0
    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
Exemplo n.º 23
0
 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
Exemplo n.º 24
0
 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'))
Exemplo n.º 25
0
 def __repr__(self):
     return '<Torrent %s (meta:%s, %s)>' % (hexlify(self.hash), True if self.meta else False, self.get_summary())
Exemplo n.º 26
0
 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
Exemplo n.º 27
0
 def __repr__(self):
     return '<Torrent %s (meta:%s, %s)>' % (hexlify(
         self.hash), True if self.meta else False, self.get_summary())
Exemplo n.º 28
0
 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'))
Exemplo n.º 29
0
    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