<gh_stars>10-100
#!/usr/bin/python

import socket
import errno
import logging
import os
import platform

if platform.system() != 'Java':
    from select import select
else:
    from select import cpython_compatible_select as select

# Disable socks support in Jython
if platform.system() != 'Java':
    import socks
else:
    if 'socks_proxy' in os.environ:
        logging.warn('Unable to honour socks_proxy environment variable, unsupported in Jython')

from prober_utils import *

settings = {
    # Note that changing these will invalidate many of the fingerprints
    'default_hello_version': TLSRecord.TLS1_0,
    'default_record_version': TLSRecord.TLS1_0,
    'socket_timeout': 5
}

class Probe(object):

    #
    # Reusable standard elements
    #
    def __init__(self):
        self.ipaddress = None

    def connect(self, ipaddress, port, starttls_mode):
        self.ipaddress = ipaddress
        # Check if we're using socks
        if 'socks_proxy' in os.environ:
            socks_host, socks_port = os.environ['socks_proxy'].split(':')
            s = socks.socksocket()
            s.setproxy(socks.PROXY_TYPE_SOCKS5, socks_host, int(socks_port))
        else:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        s.settimeout(settings['socket_timeout'])
        s.connect((ipaddress, port))

        # Do starttls if relevant
        starttls(s, port, starttls_mode)

        # return s.makefile('rw', 0)
        return s

    def test(self, sock):
        pass

    def process_response(self, sock):

        response = ''
        got_done = False

        while True:
            # Check if there is anything following the server done
            if got_done:
                # If no data then we're done (the server hasn't sent anything further)
                # we allow 500ms to give the followup time to arrive
                if not select([sock.fileno(),],[],[],0.5)[0]:
                    break

            try:
                record = read_tls_record(sock)
                response += '*(%x)' % record.version() # TODO: Not sure that recording the record layer version is worth it?
            except socket.timeout as e:
                response += 'error:timeout'
                break
            except socket.error as e:
                # response += 'error:%s|' % errno.errorcode[e.errno]
                response += 'error:%s' % e
                break
            except IOError as e:
                response += 'error:%s|' % str(e)
                break

            if record.content_type() == TLSRecord.Handshake:
                # A single handshake record can contain multiple handshake messages
                processed_bytes = 0
                while processed_bytes < record.message_length():
                    message = HandshakeMessage.from_bytes(record.message()[processed_bytes:])

                    if message.message_type() == message.ServerHello:
                        response += 'handshake:%s(%x)|' % (message.message_types[message.message_type()], message.server_version())
                    else:
                        response += 'handshake:%s|' % (message.message_types[message.message_type()])

                    if message.message_type() == HandshakeMessage.ServerHelloDone:
                        got_done = True

                    processed_bytes += message.message_length() + 4

                if got_done:
                    continue

            elif record.content_type() == TLSRecord.Alert:
                alert = AlertMessage.from_bytes(record.message())

                if alert.alert_level() == AlertMessage.Fatal:
                    response += 'alert:%s:fatal|' % alert.alert_types[alert.alert_type()]
                    break
                else:
                    response += 'alert:%s:warning|' % alert.alert_types[alert.alert_type()]
            else:
                if record.content_type() in record.content_types:
                    response += 'record:%s|' % record.content_types[record.content_type()]
                else:
                    response += 'record:type(%x)|' % record.content_type()

            if got_done:
                break

        return response

    def probe(self, ipaddress, port, starttls):
        sock = self.connect(ipaddress, port, starttls)
        try:
            result = self.test(sock)
        except socket.timeout as e:
            result = 'writeerror:timeout'
            try:
                sock.shutdown(socket.SHUT_RD_WR)
            except:
                pass
            sock.close()
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            try:
                sock.shutdown(socket.SHUT_RD_WR)
            except:
                pass
            sock.close()
            return result

        if result:
            return result
        result = self.process_response(sock)
        try:
            sock.shutdown(socket.SHUT_RD_WR)
        except:
            pass
        sock.close()
        return result


class NormalHandshake(Probe):
    '''A normal handshake'''

    def __init__(self):
        super(NormalHandshake, self).__init__()
        self.make_hello = make_hello

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())


class NormalHandshakePFS(NormalHandshake):
    '''Normal handshake with PFS ciphersuites'''

    def __init__(self):
        super(NormalHandshakePFS, self).__init__()
        self.make_hello = make_pfs_hello


class NormalHandshake11(NormalHandshake):
    '''Normal TLSv1.1 handshake'''

    def __init__(self):
        super(NormalHandshake11, self).__init__()
        self.make_hello = make_11_hello


class NormalHandshake11PFS(NormalHandshake):
    '''Normal TLSv1.1 handshake'''

    def __init__(self):
        super(NormalHandshake11PFS, self).__init__()
        self.make_hello = make_11_pfs_hello


class NormalHandshake12(NormalHandshake):
    '''Normal TLSv1.2 handshake'''

    def __init__(self):
        super(NormalHandshake12, self).__init__()
        self.make_hello = make_12_hello


class NormalHandshake12PFS(NormalHandshake):
    '''Normal TLSv1.2 handshake with PFS ciphersuites'''

    def __init__(self):
        super(NormalHandshake12PFS, self).__init__()
        self.make_hello = make_12_pfs_hello


class NormalHandshake12PFSw13(Probe):
    '''TLSv1.2 with PFS ciphers with a TLSv1.3 version (invalid TLSv1.3)'''

    def make_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_3,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_PFS_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())

class ValidSessionID(Probe):
    '''Send session ID that is too long'''

    def __init__(self):
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = MAX_CIPHERS

    def make_hello_payload(self, version, cipher_suites):
        session_id = b'0123456789' # session ID is up to 32 bytes long
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             len(session_id)) +
                 session_id + ciphers + b'\x01\x00' + b'\x00\x00')

        return hello

    def make_hello(self, version, cipher_suites):
        hello = self.make_hello_payload(version, cipher_suites)

        hello_msg = HandshakeMessage.create(HandshakeMessage.ClientHello,
                                            hello)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_2,
                                  message=hello_msg.bytes)
        return record.bytes

    def generatePacket(self):
        return self.make_hello(self.hello_version, self.ciphers)

    def test(self, sock):
        logging.debug('Sending Client Helo...')
        sock.send(self.make_hello(self.hello_version, self.ciphers))

class InvalidSessionID(Probe):
    '''Send session ID that is too long'''

    def __init__(self):
        self.hello_version = TLSRecord.TLS1_0
        self.ciphers = DEFAULT_CIPHERS

    def make_hello_payload(self, version, cipher_suites):
        session_id = b'0123456789' * 4  # session ID is up to 32 bytes long
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             len(session_id)) +
                 session_id + ciphers + b'\x01\x00' + b'\x00\x00')

        return hello

    def make_hello(self, version, cipher_suites):
        hello = self.make_hello_payload(version, cipher_suites)

        hello_msg = HandshakeMessage.create(HandshakeMessage.ClientHello,
                                            hello)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=hello_msg.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Helo...')
        sock.send(self.make_hello(self.hello_version, self.ciphers))


class InvalidSessionID12(InvalidSessionID):
    '''Send session ID that is too long in TLSv1.2 hello'''

    def __init__(self):
        super(InvalidSessionID12, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_12_CIPHERS


class InvalidSessionID12PFS(InvalidSessionID):
    '''Send session ID that is too long in PFS TLSv1.2 hello'''

    def __init__(self):
        super(InvalidSessionID12PFS, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_PFS_CIPHERS


class InvalidCiphersLength(InvalidSessionID):
    '''Send client hello with length field of ciphers that is invalid (odd)'''

    def make_hello_payload(self, version, cipher_suites):
        cipher_bytes = struct.pack('>{0}H'.format(len(cipher_suites)),
                                   *cipher_suites) + b'\x00'
        ciphers = struct.pack('>H', len(cipher_bytes)) + cipher_bytes
        hello = (struct.pack('>H32sB', version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x01\x00' + b'\x00\x00')

        return hello


class InvalidCiphersLength12(InvalidCiphersLength, InvalidSessionID12):
    '''As with InvalidCiphersLength but with TLSv1.2 helo'''
    pass


class InvalidCiphersLength12PFS(InvalidCiphersLength, InvalidSessionID12PFS):
    '''As with InvalidCiphersLength but with PFS TLSv1.2 hello'''
    pass


class InvalidExtLength(InvalidSessionID):
    '''Send client hello with length of extensions filed truncated'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x01\x00' + b'\x00')

        return hello


class InvalidExtLength12(InvalidExtLength, InvalidSessionID12):
    '''As with InvalidExtLength but in TLSv1.2 hello'''
    pass


class InvalidExtLength12PFS(InvalidExtLength, InvalidSessionID12PFS):
    '''As with InvalidExtLength but in PFS TLSv1.2 hello'''
    pass


class ExtensionsUnderflow(InvalidSessionID):
    '''Send hello with data length lower than stated size'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x01\x00'
                 b'\x00\x01'  # extensions length, just one byte
                 b'\xff\x01'  # extension ID - secure renego indication
                 b'\x00\x01'  # secure renego indication ext length
                 b'\x00')  # valid payload for extension

        return hello


class ExtensionsUnderflow12(ExtensionsUnderflow, InvalidSessionID12):
    '''As in ExtensionsUnderflow but in TLSv1.2 hello'''
    pass


class ExtensionsUnderflow12PFS(ExtensionsUnderflow, InvalidSessionID12PFS):
    '''As in ExtensionsUnderflow but in PFS TLSv1.2 hello'''
    pass


class EmptyCompression(InvalidSessionID):
    '''Send hello with no compression methods'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x00' + b'\x00\x00')

        return hello


class EmptyCompression12(EmptyCompression, InvalidSessionID12):
    '''As with EmptyCompression but in TLSv1.2 hello'''
    pass


class EmptyCompression12PFS(EmptyCompression, InvalidSessionID12PFS):
    '''As with EmptyCompression but in PFS TLSv1.2 hello'''
    pass


class CompressOnly(InvalidSessionID):
    '''Send hello with no support for uncompressed communication'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x02\x01\x40' + b'\x00\x00')

        return hello


class CompressOnly12(CompressOnly, InvalidSessionID12):
    '''As with CompressOnly but in TLSv1.2 hello'''
    pass


class CompressOnly12PFS(CompressOnly, InvalidSessionID12PFS):
    '''As with CompressOnly but in PFS TLSv1.2 hello'''
    pass


class DoubleClientHello(NormalHandshake):
    '''Two client hellos'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())


class DoubleClientHello12(DoubleClientHello, NormalHandshake12):
    '''Two client hellos, TLSv1.2'''
    pass


class DoubleClientHello12PFS(DoubleClientHello, NormalHandshake12PFS):
    '''Two client hellos, TLSv1.2 w/PFS ciphers'''
    pass


class ChangeCipherSpec(NormalHandshake):
    '''Send a hello then change cipher spec'''

    def __init__(self):
        super(ChangeCipherSpec, self).__init__()
        self.make_ccs = make_ccs
        self.record_version = TLSRecord.TLS1_0

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending ChangeCipherSpec...')
        sock.send(self.make_ccs(self.record_version))


class ChangeCipherSpec12(ChangeCipherSpec, NormalHandshake12):
    '''Send TLSv1.2 hello then change cipher spec'''

    def __init__(self):
        super(ChangeCipherSpec12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class ChangeCipherSpec12PFS(NormalHandshake12PFS, ChangeCipherSpec12):
    '''Send PFS TLSv1.2 hello then change cipher spec'''
    pass


class HelloRequest(NormalHandshake):
    '''Send a hello then hello request'''

    def __init__(self):
        super(HelloRequest, self).__init__()
        self.make_hello_request = make_hello_request
        self.record_version = TLSRecord.TLS1_0

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending Hello Request...')
        sock.send(self.make_hello_request(self.record_version))


class HelloRequest12(HelloRequest, NormalHandshake12):
    '''Send a TLSv1.2 hello then hello request'''

    def __init__(self):
        super(HelloRequest12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class HelloRequest12PFS(NormalHandshake12PFS, HelloRequest12):
    '''Send a PFS TLSv1.2 hello then hello request'''
    pass


class EmptyChangeCipherSpec(NormalHandshake):
    '''Send a hello then an empty change cipher spec'''

    def __init__(self):
        super(EmptyChangeCipherSpec, self).__init__()
        self.record_version = TLSRecord.TLS1_0

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending Empty ChangeCipherSpec...')

        record = TLSRecord.create(content_type=TLSRecord.ChangeCipherSpec,
                                  version=self.record_version,
                                  message='')
        sock.send(record.bytes)


class EmptyChangeCipherSpec12(EmptyChangeCipherSpec, NormalHandshake12):
    '''Send TLSv1.2 hello then an empty change cipher spec'''

    def __init__(self):
        super(EmptyChangeCipherSpec12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class EmptyChangeCipherSpec12PFS(NormalHandshake12PFS,
                                 EmptyChangeCipherSpec12):
    '''Send PFS TLSv1.2 hello then an empty change cipher spec'''
    pass


class BadHandshakeMessage(Probe):
    '''An invalid handshake message'''

    def make_bad_handshake(self):
        content = 'Something'

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=content)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(make_hello())
        logging.debug('Sending bad handshake message...')
        sock.send(self.make_bad_handshake())


class OnlyECCipherSuites(Probe):
    '''Try connecting with ECC cipher suites only'''

    def make_ec_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_0,
                                          b'01234567890123456789012345678901',
                                          [TLS_ECDH_RSA_WITH_RC4_128_SHA,
                                           TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
                                           TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
                                           TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
                                           TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                                           TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                                           TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256])

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_ec_hello())


class Heartbeat(NormalHandshake):
    '''Try to send a heartbeat message'''

    def __init__(self):
        super(Heartbeat, self).__init__()
        self.record_version = TLSRecord.TLS1_0

    def make_hb_hello(self):
        hb_extension = HeartbeatExtension.create()
        return self.make_hello([hb_extension])

    def make_heartbeat(self):
        heartbeat = HeartbeatMessage.create(HeartbeatMessage.HeartbeatRequest,
                                            'XXXX')

        record = TLSRecord.create(content_type=TLSRecord.Heartbeat,
                                  version=self.record_version,
                                  message=heartbeat.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hb_hello())
        logging.debug('Sending Heartbeat...')
        sock.send(self.make_heartbeat())


class Heartbeat12(NormalHandshake12, Heartbeat):
    '''Try to send a heartbeat message in TLSv1.2 connection'''

    def __init__(self):
        super(Heartbeat12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class Heartbeat12PFS(NormalHandshake12PFS, Heartbeat12):
    '''Try to send a hearbeat message in PFS TLSv1.2 connection'''
    pass


class Heartbleed(Heartbeat):
    '''Try to send a heartbleed attack'''

    def make_heartbeat(self):
        heartbeat = HeartbeatMessage.create(HeartbeatMessage.HeartbeatRequest,
                                            'XXXX', 0x4000)

        record = TLSRecord.create(content_type=TLSRecord.Heartbeat,
                                  version=self.record_version,
                                  message=heartbeat.bytes)

        #hexdump(record.bytes)
        return record.bytes


class Heartbleed12(Heartbeat12, Heartbleed):
    '''Try to send a heartbleed attack in TLSv1.2'''
    pass


class Heartbleed12PFS(Heartbeat12PFS, Heartbleed):
    '''Try to send a heartbleed attack in TLSv1.2'''
    pass


class HighTLSVersion(Probe):
    '''Set a high TLS version in the record'''

    def make_hello(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)
        return hello

    def make_high_tls_hello(self):
        hello = self.make_hello()

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=0x400,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_high_tls_hello())


class HighTLSVersion12(HighTLSVersion):
    '''Set a high TLS version in the record of TLSv1.2 hello'''

    def make_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_12_CIPHERS)
        return hello


class HighTLSVersion12PFS(HighTLSVersion):
    '''Set a high TLS version in the record of PFS TLSv1.2 hello'''

    def make_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_PFS_CIPHERS)
        return hello


class VeryHighTLSVersion(HighTLSVersion):
    '''Set a very high TLS version in the record'''

    def make_high_tls_hello(self):
        hello = self.make_hello()

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=0xffff,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes


class VeryHighTLSVersion12(HighTLSVersion12, VeryHighTLSVersion):
    '''Set a very high TLS version in the record of TLSv1.2 hello'''
    pass


class VeryHighTLSVersion12PFS(HighTLSVersion12PFS, VeryHighTLSVersion):
    '''Set a very high TLS version in the record of PFS TLSv1.2 hello'''
    pass


class ZeroTLSVersion(HighTLSVersion):
    '''Set a zero version in the record'''

    def make_high_tls_hello(self):
        hello = self.make_hello()

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=0x000,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes


class ZeroTLSVersion12(HighTLSVersion12, ZeroTLSVersion):
    '''Set a zero version in the record of TLSv1.2 hello'''
    pass


class ZeroTLSVersion12PFS(HighTLSVersion12PFS, ZeroTLSVersion):
    '''Set a zero version in the record of PFS TLSv1.2 hello'''
    pass


class HighHelloVersion(Probe):
    '''Set a high version in the hello'''

    def __init__(self):
        super(HighHelloVersion, self).__init__()
        self.hello_version = 0x400
        self.hello_ciphers = DEFAULT_CIPHERS

    def make_high_tls_hello(self):
        hello = ClientHelloMessage.create(self.hello_version,
                                          b'01234567890123456789012345678901',
                                          self.hello_ciphers)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_high_tls_hello())


class HighHelloVersionNew(HighHelloVersion):
    '''Set a high version in a hello with more ciphers'''

    def __init__(self):
        super(HighHelloVersionNew, self).__init__()
        self.hello_ciphers = DEFAULT_12_CIPHERS


class HighHelloVersionPFS(HighHelloVersion):
    '''Set a high version in a hello with PFS ciphers'''

    def __init__(self):
        super(HighHelloVersionPFS, self).__init__()
        self.hello_ciphers = DEFAULT_PFS_CIPHERS


class VeryHighHelloVersion(HighHelloVersion):
    '''Set a very high version in the hello'''

    def __init__(self):
        super(VeryHighHelloVersion, self).__init__()
        self.hello_version = 0xffff


class VeryHighHelloVersionNew(HighHelloVersionNew, VeryHighHelloVersion):
    '''Set a very high version in the hello with more ciphers'''
    pass


class VeryHighHelloVersionPFS(HighHelloVersionPFS, VeryHighHelloVersion):
    '''Set a very high version in the hello with PFS ciphers'''
    pass


class ZeroHelloVersion(Probe):
    '''Set a zero version in the hello'''

    def make_zero_tls_hello(self):
        hello = ClientHelloMessage.create(0x000,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_zero_tls_hello())


class BadContentType(Probe):
    '''Use an invalid content type in the record'''

    def make_bad_content_type(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=17,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_bad_content_type())


class RecordLengthOverflow(Probe):
    '''Make the record length exceed the stated one'''

    def make_record_length_overflow(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes,
                                  length=0x0001)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_record_length_overflow())


class RecordLengthUnderflow(Probe):
    '''Make the record shorter than the specified length'''

    def make_record_length_underflow(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes,
                                  length=0xffff)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        try:
            sock.send(self.make_record_length_underflow())
        except socket.timeout as e:
            result = 'writeerror:timeout'
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            return result


class EmptyRecord(NormalHandshake):
    '''Send an empty record then the hello'''

    def make_empty_record(self):
        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message='')

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending empty record...')
        sock.send(self.make_empty_record())
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())


class EmptyRecord12(NormalHandshake12, EmptyRecord):
    '''Send an empty record then TLSv1.2 hello'''
    pass


class EmptyRecord12PFS(NormalHandshake12PFS, EmptyRecord):
    '''Send and empty record then PFS TLSv1.2 hello'''
    pass


class TwoInvalidPackets(Probe):
    '''Send two invalid messages'''

    def test(self, sock):
        logging.debug('Sending split hello...')
        part_one = b'<tls.record.TLSRecord object at 0x7fd2dc0906d0>'
        part_two = b'<tls.record.TLSRecord object at 0x7fd2dc090690>'
        sock.send(part_one)
        try:
            sock.send(part_two)
        except socket.timeout as e:
            result = 'writeerror:timeout'
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            return result


class SplitHelloRecords(Probe):
    '''Split the hello over two records'''

    def make_split_hello(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        first = hello.bytes[:10]
        second = hello.bytes[10:]

        record_one = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=first)
        record_two = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=0x301,
                                      message=second)

        #hexdump(record.bytes)
        return record_one.bytes, record_two.bytes

    def test(self, sock):
        logging.debug('Sending split hello...')
        part_one, part_two = self.make_split_hello()
        sock.send(part_one)
        try:
            sock.send(part_two)
        except socket.timeout as e:
            result = 'writeerror:timeout'
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            return result


class SplitHelloRecords12(SplitHelloRecords):
    '''Split the TLS1.2 hello over two records'''

    def make_split_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_12_CIPHERS)

        first = hello.bytes[:10]
        second = hello.bytes[10:]

        record_one = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=first)
        record_two = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=second)

        #hexdump(record.bytes)
        return record_one.bytes, record_two.bytes


class SplitHelloRecords12PFS(SplitHelloRecords):
    '''Split the TLS1.2 PFS hello over two records'''

    def make_split_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_PFS_CIPHERS)

        first = hello.bytes[:10]
        second = hello.bytes[10:]

        record_one = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=first)
        record_two = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=second)

        #hexdump(record.bytes)
        return record_one.bytes, record_two.bytes


class SplitHelloPackets(NormalHandshake):
    '''Split the hello over two packets'''

    def test(self, sock):
        logging.debug('Sending Client Hello part one...')
        record = self.make_hello()
        sock.send(record[:10])
        # sock.flush()
        logging.debug('Sending Client Hello part two...')
        sock.send(record[10:])


class SplitHelloPackets12(SplitHelloPackets, NormalHandshake12):
    '''Split the TLS1.2 hello over two packets'''
    pass


class SplitHelloPackets12PFS(SplitHelloPackets, NormalHandshake12PFS):
    '''Split the TLS1.2 PFS hello over two packets'''
    pass


class NoCiphers(Probe):
    '''Send an empty cipher list'''

    def __init__(self):
        super(NoCiphers, self).__init__()
        self.hello_version = settings['default_hello_version']

    def make_no_ciphers_hello(self):
        hello = ClientHelloMessage.create(self.hello_version,
                                          b'01234567890123456789012345678901',
                                          [])

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending No ciphers Hello...')
        sock.send(self.make_no_ciphers_hello())


class NoCiphers12(NoCiphers):
    '''Send and empty cipher list in TLSv1.2 hello'''

    def __init__(self):
        super(NoCiphers12, self).__init__()
        self.hello_version = TLSRecord.TLS1_2


class SNIWrongName(NormalHandshake):
    '''Send a server name indication for a non-matching name'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(name)
        return self.make_hello([sni_extension])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello('thisisnotyourname'))


class SNIWrongName12(NormalHandshake12, SNIWrongName):
    '''Send a server name indication for non-matching name in TLSv1.2 hello'''
    pass


class SNIWrongName12PFS(NormalHandshake12PFS, SNIWrongName):
    '''Send a SNI extension for non-matching name in PFS TLSv1.2 hello'''
    pass


class SNILongName(SNIWrongName):
    '''Send a server name indication with a long name'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello('x'*500))


class SNILongName12(NormalHandshake12, SNILongName):
    '''Send a server name indication with a long name in TLSv1.2 hello'''
    pass


class SNILongName12PFS(NormalHandshake12PFS, SNILongName):
    '''Send a server name indication with a long name in PFS TLSv1.2 hello'''
    pass


class SNIEmptyName(SNIWrongName):
    '''Send a server name indication with an empty name'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello(''))


class SNIEmptyName12(NormalHandshake12, SNIEmptyName):
    '''Send a server name indication with an empty name in TLSv1.2 hello'''
    pass


class SNIEmptyName12PFS(NormalHandshake12PFS, SNIEmptyName):
    '''Send a server name indication with an empty name in PFS TLSv1.2 hello'''
    pass


class SNIOneWrong(NormalHandshake):
    '''Send server name indication with two names, one wrong'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(None,
                                                   (name, 'thisisnotyourname'))
        record = self.make_hello([sni_extension])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello(self.ipaddress))


class SNIOneWrong12(SNIOneWrong, NormalHandshake12):
    '''Send server name indication with two names, one wrong in TLS1.2 hello'''
    pass


class SNIOneWrong12PFS(SNIOneWrong, NormalHandshake12PFS):
    '''As in SNIOneWrong but in PFS TLS1.2 hello'''
    pass


class SNIWithDifferentType(NormalHandshake):
    '''Send server name indication with two names, one not of host_name type'''

    def make_sni_ext(self, server_names):
        encoded_names = b''.join(struct.pack('!BH', name_type, len(name))
                                + str.encode(name) for name_type, name in server_names)
        ext_data = struct.pack('!H', len(encoded_names)) + encoded_names
        return Extension.create(extension_type=Extension.ServerName,
                                data=ext_data)

    def make_sni_hello(self, server_names):
        sni_extension = self.make_sni_ext(server_names)

        record = self.make_hello([sni_extension])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        server_names = []
        server_names += [(ServerNameExtension.HostName, self.ipaddress)]
        # only type 0 (HostName) is defined, any other should be ignored
        server_names += [(4, '<binary-data>')]

        sock.send(self.make_sni_hello(server_names))


class SNIWithDifferentType12(SNIWithDifferentType, NormalHandshake12):
    '''As with SNIWithDifferentType but in TLSv1.2 hello'''
    pass


class SNIWithDifferentType12PFS(SNIWithDifferentType, NormalHandshake12PFS):
    '''As with SNIWithDifferentType but in PFS TLSv1.2 hello'''
    pass


class SNIDifferentTypeRev(SNIWithDifferentType):
    '''Send hello like in SNIWithDifferentType but reverse order of names'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        server_names = []
        # only type 0 (HostName) is defined, any other should be ignored
        server_names += [(4, '<binary-data>')]
        server_names += [(ServerNameExtension.HostName, self.ipaddress)]

        sock.send(self.make_sni_hello(server_names))


class SNIDifferentTypeRev12(SNIDifferentTypeRev, NormalHandshake12):
    '''As with SNIDifferentTypeRev but in TLSv1.2 hello'''
    pass


class SNIDifferentTypeRev12PFS(SNIDifferentTypeRev, NormalHandshake12PFS):
    '''As with SNIDifferentTypeRev but in PFS TLSv1.2 hello'''
    pass


class SNIOverflow(NormalHandshake):
    '''Send server name indication with data length exceeding stated size'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(name)
        # first four bytes are the header, last one we truncate to exceed size
        ext_data = sni_extension.bytes[4:-1]
        sni_extension = Extension.create(extension_type=Extension.ServerName,
                                         data=ext_data)

        record = self.make_hello([sni_extension])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello(self.ipaddress))


class SNIOverflow12(SNIOverflow, NormalHandshake12):
    '''as with SNIOverflow but in TLSv1.2 hello'''
    pass


class SNIOverflow12PFS(SNIOverflow, NormalHandshake12PFS):
    '''as with SNIOverflow but in TLSv1.2 hello'''
    pass


class SNIUnderflow(SNIOverflow):
    '''Send server name indication with data length smaller than size inside'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(name)
        # first four bytes are the header
        ext_data = sni_extension.bytes[4:] + b'\x00\x00\x00'
        sni_extension = Extension.create(extension_type=Extension.ServerName,
                                         data=ext_data)

        record = self.make_hello([sni_extension])

        return record


class SNIUnderflow12(SNIUnderflow, NormalHandshake12):
    '''As with SNIUnderflow, but in TLSv1.2 hello'''
    pass


class SNIUnderflow12PFS(SNIUnderflow, NormalHandshake12PFS):
    '''As with SNIUnderflow, but in PFS TLSv1.2 hello'''
    pass


class SecureRenegoOverflow(NormalHandshake):
    '''Send secure renegotiation with data length exceeding stated size'''

    def make_secure_renego_ext(self, payload):
        secure_renego = Extension.create(
            extension_type=Extension.RenegotiationInfo,
            data=payload)
        return self.make_hello([secure_renego])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte of secure renegotiation extension specifies the
        # length of the array of bytes in it, but don't provide the
        # required amount
        sock.send(self.make_secure_renego_ext(b'\x0c0123456789'))


class SecureRenegoOverflow12(SecureRenegoOverflow, NormalHandshake12):
    '''As with SecureRenegotOverflow, inside TLSv1.2 hello'''
    pass


class SecureRenegoOverflow12PFS(SecureRenegoOverflow, NormalHandshake12PFS):
    '''As with SecureRenegoOverflow, inside TLSv1.2 PFS hello'''
    pass


class SecureRenegoUnderflow(SecureRenegoOverflow):
    '''Send secure renegotiation with data length lower than stated size'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # again, first byte specifies zero-length array, rest of bytes
        # are just padding to make the extension large
        sock.send(self.make_secure_renego_ext(b'\x00\x00\x00\x00\x00'))


class SecureRenegoUnderflow12(SecureRenegoUnderflow, NormalHandshake12):
    '''As with SecureRenegoUnderflow, inside TLSv1.2 hello'''
    pass


class SecureRenegoUnderflow12PFS(SecureRenegoUnderflow, NormalHandshake12PFS):
    '''As with SecureRenegoUnderflow, inside PFS TLSv1.2 hello'''
    pass


class SecureRenegoNonEmpty(SecureRenegoOverflow):
    '''Send secure renegotiation with renegotiation payload'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # send a correctly formatted extension, but with a non-empty
        # payload (indicating renegotiated connection)
        sock.send(self.make_secure_renego_ext(b'\x0c012345678901'))


class SecureRenegoNonEmpty12(SecureRenegoNonEmpty, NormalHandshake12):
    '''Send secure renegotiation with renegotiation payload in TLSv1.2 hello'''
    pass


class SecureRenegoNonEmpty12PFS(SecureRenegoNonEmpty, NormalHandshake12PFS):
    '''As with SecureRenegoNonEmpty12, but with PFS ciphers'''
    pass


class SecureRenegoNull(SecureRenegoOverflow):
    '''Send secure renegotiation extension that is completely empty'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # While the proper formatting is to send an empty array, and not
        # no array, some servers still accept it
        sock.send(self.make_secure_renego_ext(b''))


class SecureRenegoNull12(SecureRenegoNull, NormalHandshake12):
    '''As with SecureRenegoNull, but in TLSv1.2 hello'''
    pass


class SecureRenegoNull12PFS(SecureRenegoNull, NormalHandshake12PFS):
    '''As with SecureRenegoNull, but in PFS TLSv1.2 hello'''
    pass


class MaxFragmentNull(NormalHandshake):
    '''Send maximum fragment length extension that is completely empty'''

    def make_fragment_hello(self, payload):
        max_fragment = Extension.create(
            extension_type=Extension.MaxFragmentLength,
            data=payload)

        record = self.make_hello([max_fragment])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension needs a single byte value, don't provide it
        sock.send(self.make_fragment_hello(b''))


class MaxFragmentNull12(MaxFragmentNull, NormalHandshake12):
    '''As with MaxFragmentNull, but in TLSv1.2 hello'''
    pass


class MaxFragmentNull12PFS(MaxFragmentNull, NormalHandshake12PFS):
    '''As with MaxFragmentNull, but in PFS TLSv1.2 hello'''
    pass


class MaxFragmentInvalid(MaxFragmentNull):
    '''Send maximum fragment length extension with invalid value'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid values are between 1 and 4 inclusive
        sock.send(self.make_fragment_hello(b'\x08'))


class MaxFragmentInvalid12(MaxFragmentInvalid, NormalHandshake12):
    '''As with MaxFragmentInvalid, but in TLSv1.2 hello'''
    pass


class MaxFragmentInvalid12PFS(MaxFragmentInvalid, NormalHandshake12PFS):
    '''As with MaxFragmentInvalid, but in PFS TLSv1.2 hello'''
    pass


class ClientCertURLsNotNull(NormalHandshake):
    '''Send client certificate URL indication extension that is not empty'''

    def make_cert_urls_hello(self, payload):
        client_cert_url_ext = Extension.create(
            extension_type=Extension.ClientCertificateUrl,
            data=payload)

        record = self.make_hello([client_cert_url_ext])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # correctly formatted does not include any data
        sock.send(self.make_cert_urls_hello(b'\x08\x00'))


class ClientCertURLsNotNull12(ClientCertURLsNotNull, NormalHandshake12):
    '''As with ClientCertURLsNotNull, but in TLSv1.2 hello'''
    pass


class ClientCertURLsNotNull12PFS(ClientCertURLsNotNull, NormalHandshake12PFS):
    '''As with ClientCertURLsNotNull, but in PFS TLSv1.2 hello'''
    pass


class TrustedCANull(NormalHandshake):
    '''Send trusted CA keys extension with completely empty payload'''

    def make_trusted_ca_hello(self, payload):
        trusted_ca_ext = Extension.create(
            extension_type=Extension.TrustedCAKeys,
            data=payload)

        record = self.make_hello([trusted_ca_ext])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal formatting is a complex structure
        sock.send(self.make_trusted_ca_hello(b''))


class TrustedCANull12(TrustedCANull, NormalHandshake12):
    '''As with TrustedCANull but in TLSv1.2 hello'''
    pass


class TrustedCANull12PFS(TrustedCANull, NormalHandshake12PFS):
    '''As with TrustedCANull, but in PFS TLSv1.2 hello'''
    pass


class TrustedCAOverflow(TrustedCANull):
    '''Send trusted CA keys extension smaller than length inside indicates'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # in a normal structure, the first two bytes are the overall length
        # of list with extension data
        # a typical payload includes type (1B) and sha1 hash (20B)
        sock.send(self.make_trusted_ca_hello(b'\x00\x15'))


class TrustedCAOverflow12(TrustedCAOverflow, NormalHandshake12):
    '''As with TrustedCAOverflow but in TLSv1.2 hello'''
    pass


class TrustedCAOverflow12PFS(TrustedCAOverflow, NormalHandshake12PFS):
    '''As with TrustedCAOverflow but in PFS TLSv1.2 hello'''
    pass


class TrustedCAUnderflow(TrustedCANull):
    '''Send trusted CA keys extension larger than length inside indicates'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')

        # type key_sha1_hash + sha1 hash (20 bytes)
        authority = b'\x01' + b'a'*20
        # payload has a 2 byte length and then an array of items,
        # add null byte at end to cause the underflow
        ext_data = struct.pack('!H', len(authority)) + authority + b'\x00'

        sock.send(self.make_trusted_ca_hello(ext_data))


class TrustedCAUnderflow12(TrustedCAUnderflow, NormalHandshake12):
    '''As with TrustedCAUnderflow but in TLSv1.2 hello'''
    pass


class TrustedCAUnderflow12PFS(TrustedCAUnderflow, NormalHandshake12PFS):
    '''As with TrustedCAUnderflow but in PFS TLSv1.2 hello'''
    pass


class TruncatedHMACNotNull(NormalHandshake):
    '''Send a truncated HMAC extension with a non empty payload'''

    def make_truncated_hmac_hello(self, payload):
        truncated_hmac = Extension.create(
            extension_type=Extension.TruncateHMAC,
            data=payload)

        record = self.make_hello([truncated_hmac])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # properly formatted extension has no data at all
        sock.send(self.make_truncated_hmac_hello(b'\x0c'))


class TruncatedHMACNotNull12(TruncatedHMACNotNull, NormalHandshake12):
    '''As with TruncatedHMACNotNull but in TLSv1.2 hello'''
    pass


class TruncatedHMACNotNull12PFS(TruncatedHMACNotNull, NormalHandshake12PFS):
    '''As with TruncatedHMACNotNull but in PFS TLSv1.2 hello'''
    pass


class OCSPNull(NormalHandshake):
    '''Send status request extension with empty payload'''

    def make_ocsp_hello(self, payload):
        status_request = Extension.create(
            extension_type=Extension.StatusRequest,
            data=payload)

        record = self.make_hello([status_request])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normally the status request is a complex structure, don't include
        # it
        sock.send(self.make_ocsp_hello(b''))


class OCSPNull12(OCSPNull, NormalHandshake12):
    '''As with OCSPNull but in TLSv1.2 hello'''
    pass


class OCSPNull12PFS(OCSPNull, NormalHandshake12PFS):
    '''As with OCSPNull but in PFS TLSv1.2 hello'''
    pass


class OCSPOverflow(OCSPNull):
    '''Send status request ext smaller than the length inside indicates'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the request has three fields - type (one byte) and two arrays
        # with 2 byte long headers, truncate the second length header
        sock.send(self.make_ocsp_hello(b'\x01\x00\x00\x00'))


class OCSPOverflow12(OCSPOverflow, NormalHandshake12):
    '''As with OCSPOverflow but in TLSv1.2 hello'''
    pass


class OCSPOverflow12PFS(OCSPOverflow, NormalHandshake12PFS):
    '''As with OCSPOverflow but in PFS TLSv1.2 hello'''
    pass


class OCSPUnderflow(OCSPNull):
    '''Send status request ext larger than the length inside indicate'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # correctly formed request, two extra zero bytes
        sock.send(self.make_ocsp_hello(b'\x01' + b'\x00' * 6))


class OCSPUnderflow12(OCSPUnderflow, NormalHandshake12):
    '''As with OCSPUnderflow but in TLSv1.2 hello'''
    pass


class OCSPUnderflow12PFS(OCSPUnderflow, NormalHandshake12PFS):
    '''As with OCSPUnderflow but in PFS TLSv1.2 hello'''
    pass


class DoubleExtension(NormalHandshake):
    '''Duplicate secure renegotiation extension'''

    def make_double_ext_hello(self):
        secure_renego = Extension.create(
            extension_type=Extension.RenegotiationInfo,
            data=b'\x00')

        record = self.make_hello([secure_renego,
                                  secure_renego])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # correct Client Hello messages must not contain two extensions
        # of the same type
        sock.send(self.make_double_ext_hello())


class DoubleExtension12(DoubleExtension, NormalHandshake12):
    '''Duplicate secure renegotiation extension in TLSv1.2 hello'''
    pass


class DoubleExtension12PFS(DoubleExtension, NormalHandshake12PFS):
    '''Duplicate secure renegotiation extension in PFS TLSv1.2 hello'''
    pass


class UserMappingNull(NormalHandshake):
    '''Send empty user mapping extension in hello'''

    def make_user_mapping_ext(self, value):
        user_mapping_ext = Extension.create(
            extension_type=6,
            data=value)
        return self.make_hello([user_mapping_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # extension consists of an array and the array needs at least one
        # element, don't send any
        sock.send(self.make_user_mapping_ext(b''))


class UserMappingNull12(UserMappingNull, NormalHandshake12):
    '''Send empty user mapping extension in TLSv1.2 hello'''
    pass


class UserMappingNull12PFS(UserMappingNull, NormalHandshake12PFS):
    '''Send empty user mapping extension in PFS TLSv1.2 hello'''
    pass


class UserMappingOverflow(UserMappingNull):
    '''Send user mapping extension with length longer than present in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # extension consists of an array and the array needs at least one
        # element, send the length of array (one byte) longer than payload size
        sock.send(self.make_user_mapping_ext(b'\x02\x40'))


class UserMappingOverflow12(UserMappingOverflow, NormalHandshake12):
    '''As with UserMappingOverflow but in TLSv1.2 hello'''
    pass


class UserMappingOverflow12PFS(UserMappingOverflow, NormalHandshake12PFS):
    '''As with UserMappingOverflow but in PFS TLSv1.2 hello'''
    pass


class ClientAuthzNull(NormalHandshake):
    '''Send empty client authz extension in hello'''

    def make_client_authz_hello(self, value):
        client_authz_ext = Extension.create(
            extension_type=7,
            data=value)
        return self.make_hello([client_authz_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_client_authz_hello(b''))


class ClientAuthzNull12(ClientAuthzNull, NormalHandshake12):
    '''Send empty client authz extension in TLSv1.2 hello'''
    pass


class ClientAuthzNull12PFS(ClientAuthzNull, NormalHandshake12PFS):
    '''Send empty client authz extension in PFS TLSv1.2 hello'''
    pass


class ClientAuthzOverflow(ClientAuthzNull):
    '''Send client authz extension with length longer than data in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has one byte length as first element then
        # the array, make the array length longer than real payload
        sock.send(self.make_client_authz_hello(b'\x04\x00\x01'))


class ClientAuthzOverflow12(ClientAuthzOverflow, NormalHandshake12):
    '''As with ClientAuthzOverflow but in TLSv1.2 hello'''
    pass


class ClientAuthzOverflow12PFS(ClientAuthzOverflow, NormalHandshake12PFS):
    '''As with ClientAuthzOverflow but in PFS TLSv1.3 hello'''
    pass


class ServerAuthzNull(ClientAuthzNull):
    '''Send empty server authz extension in hello'''

    def make_client_authz_hello(self, value):
        server_authz_ext = Extension.create(
            extension_type=8,
            data=value)
        return self.make_hello([server_authz_ext])


class ServerAuthzNull12(ServerAuthzNull, NormalHandshake12):
    '''Send empty server authz extension in TLSv1.2 hello'''
    pass


class ServerAuthzNull12PFS(ServerAuthzNull, NormalHandshake12PFS):
    '''Send empty server authz extension in PFS TLSv1.2 hello'''
    pass


class ServerAuthzOverflow(ServerAuthzNull, ClientAuthzOverflow):
    '''Send server authz extension with length longer than data in hello'''
    pass


class ServerAuthzOverflow12(ServerAuthzOverflow, NormalHandshake12):
    '''As with ServerAuthzOverflow but in TLSv1.2 hello'''
    pass


class ServerAuthzOverflow12PFS(ServerAuthzOverflow, NormalHandshake12PFS):
    '''As with ServerAuthzOverflow but in PFS TLSv1.2 hello'''
    pass


class CertTypeNull(NormalHandshake):
    '''Send empty cert type extension in hello'''

    def make_cert_type_hello(self, value):
        cert_type_ext = Extension.create(
            extension_type=9,
            data=value)
        return self.make_hello([cert_type_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_cert_type_hello(b''))


class CertTypeNull12(CertTypeNull, NormalHandshake12):
    '''Send empty cert type extension in TLSv1.2 hello'''
    pass


class CertTypeNull12PFS(CertTypeNull, NormalHandshake12PFS):
    '''Send empty cert type extension in PFS TLSv1.2 hello'''
    pass


class CertTypeOverflow(CertTypeNull):
    '''Send cert type extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte is a length of array, send invalid one
        sock.send(self.make_cert_type_hello(b'\x04\x01'))


class CertTypeOverflow12(CertTypeOverflow, NormalHandshake12):
    '''Send cert type extension with too large length in TLSv1.2 hello'''
    pass


class CertTypeOverflow12PFS(CertTypeOverflow, NormalHandshake12PFS):
    '''Send cert type extension with too large length in PFS TLSv1.2 hello'''
    pass


class SupportedGroupsNull(NormalHandshake):
    '''Send empty supported groups extension in hello'''

    def make_supported_groups_hello(self, value):
        supported_groups_ext = Extension.create(
            extension_type=10,
            data=value)
        return self.make_hello([supported_groups_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_supported_groups_hello(b''))


class SupportedGroupsNull12(SupportedGroupsNull, NormalHandshake12):
    '''Send empty supported groups extension in TLSv1.2 hello'''
    pass


class SupportedGroupsNull12PFS(SupportedGroupsNull, NormalHandshake12PFS):
    '''Send empty supported groups extension in PFS TLSv1.2 hello'''
    pass


class SupportedGroupsOddLen(SupportedGroupsNull):
    '''Send supported groups extension with invalid length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has a two byte length and two byte elements,
        # truncate the second element
        sock.send(self.make_supported_groups_hello(b'\x00\x03\x00\x17\x00'))


class SupportedGroupsOddLen12(SupportedGroupsOddLen, NormalHandshake12):
    '''Send supported groups extension with invalid length in TLSv1.2 hello'''
    pass


class SupportedGroupsOddLen12PFS(SupportedGroupsOddLen, NormalHandshake12PFS):
    '''As with SupportedGroupsOddLen but in PFS TLSv1.2 hello'''
    pass


class SupportedGroupsOverflow(SupportedGroupsNull):
    '''Send supported groups extension with length larger than data'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has a two byte length and two byte elements,
        # truncate the whole second element
        sock.send(self.make_supported_groups_hello(b'\x00\x04\x00\x17'))


class SupportedGroupsOverflow12(SupportedGroupsOverflow, NormalHandshake12):
    '''As with SupportedGroupsOverflow but in TLSv1.2 hello'''
    pass


class SupportedGroupsOverflow12PFS(SupportedGroupsOverflow,
        NormalHandshake12PFS):
    '''As with SupportedGroupsOverflow but in PFS TLSv1.2 hello'''
    pass


class ECPointFormatsNull(NormalHandshake):
    '''Send empty ec point formats extension in hello'''

    def make_point_formats_hello(self, value):
        point_formats_ext = Extension.create(
            extension_type=11,
            data=value)
        return self.make_hello([point_formats_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_point_formats_hello(b''))


class ECPointFormatsNull12(ECPointFormatsNull, NormalHandshake12):
    '''Send empty ec point formats extension in TLSv1.2 hello'''
    pass


class ECPointFormatsNull12PFS(ECPointFormatsNull, NormalHandshake12PFS):
    '''Send empty ec point formats extension in PFS TLSv1.2 hello'''
    pass


class ECPointFormatsOverflow(ECPointFormatsNull):
    '''Send ec point formats extension with length larger than data in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte is the length of array, send too large one
        sock.send(self.make_point_formats_hello(b'\x04\x00'))


class ECPointFormatsOverflow12(ECPointFormatsOverflow, NormalHandshake12):
    '''As with ECPointFormatsOverflow but in TLSv1.2 hello'''
    pass


class ECPointFormatsOverflow12PFS(ECPointFormatsOverflow,
                                   NormalHandshake12PFS):
    '''As with ECPointFormatsOverflow but in PFS TLSv1.2 hello'''
    pass


class ECPointFormatsCompOnly(ECPointFormatsNull):
    '''Send ec point formats extension without uncompressed format'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the uncompressed format is mandatory, send extension without it
        sock.send(self.make_point_formats_hello(b'\x02\x01\x02'))


class ECPointFormatsCompOnly12(ECPointFormatsCompOnly, NormalHandshake12):
    '''As with ECPointFormatsCompOnly but in TLSv1.2 hello'''
    pass


class ECPointFormatsCompOnly12PFS(ECPointFormatsCompOnly,
                                   NormalHandshake12PFS):
    '''As with ECPointFormatsCompOnly but in PFS TLS v1.2 hello'''
    pass


class SRPNull(NormalHandshake):
    '''Send empty srp extension in hello'''

    def make_srp_hello(self, value):
        srp_ext = Extension.create(
            extension_type=12,
            data=value)
        return self.make_hello([srp_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normally the extension has client's identity, don't include any
        sock.send(self.make_srp_hello(b''))


class SRPNull12(SRPNull, NormalHandshake12):
    '''Send empty srp extension in TLSv1.2 hello'''
    pass


class SRPNull12PFS(SRPNull, NormalHandshake12PFS):
    '''Send empty srp extension in PFS TLSv1.2 hello'''
    pass


class SRPOverflow(SRPNull):
    '''Send srp extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte is the length, send too large
        sock.send(self.make_srp_hello(b'\x06test'))


class SRPOverflow12(SRPOverflow, NormalHandshake12):
    '''Send srp extension with too large length in TLSv1.2 hello'''
    pass


class SRPOverflow12PFS(SRPOverflow, NormalHandshake12PFS):
    '''Send srp extension with too large length in PFS TLSv1.2 hello'''
    pass


class SigAlgsNull(NormalHandshake):
    '''Send empty signature algorithms extension in hello'''

    def make_signature_alg_hello(self, value):
        sig_algs_ext = Extension.create(
            extension_type=13,
            data=value)
        return self.make_hello([sig_algs_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_signature_alg_hello(b''))


class SigAlgsNull12(SigAlgsNull, NormalHandshake12):
    '''Send empty signature algorithms extension in TLSv1.2 hello'''
    pass


class SigAlgsNull12PFS(SigAlgsNull, NormalHandshake12PFS):
    '''Send empty signature algorithms extension in PFS TLSv1.2 hello'''
    pass


class SigAlgsOddLen(SigAlgsNull):
    '''Send signature algorithms extensions with invalid length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has two byte long elements, truncate the last one
        sock.send(self.make_signature_alg_hello(b'\x00\x05'
                                                 b'\x04\x01'
                                                 b'\x04\x03\x04'))

class SigAlgsOddLen12(SigAlgsOddLen, NormalHandshake12):
    '''As in SigAlgsOddLen but in TLSv1.2 hello'''
    pass


class SigAlgsOddLen12PFS(SigAlgsOddLen, NormalHandshake12PFS):
    '''As in SigAlgsOddLen but in PFS TLSv1.2 hello'''
    pass


class SigAlgsOverflow(SigAlgsNull):
    '''Send signature algorithms extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the first two bytes are the length of the array, send too large one
        sock.send(self.make_signature_alg_hello(b'\x00\x06'
                                                 b'\x04\x01'
                                                 b'\x04\x03'))


class SigAlgsOverflow12(SigAlgsOverflow, NormalHandshake12):
    '''As in SigAlgsOverflow but in TLSv1.2 hello'''
    pass


class SigAlgsOverflow12PFS(SigAlgsOverflow, NormalHandshake12PFS):
    '''As in SigAlgsOverflow but in PFS TLSv1.2 hello'''
    pass


class UseSrtpNull(NormalHandshake):
    '''Send empty use srtp extension in hello'''

    def make_use_srtp_hello(self, value):
        use_srtp_ext = Extension.create(
            extension_type=14,
            data=value)
        return self.make_hello([use_srtp_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_use_srtp_hello(b''))


class UseSrtpNull12(UseSrtpNull, NormalHandshake12):
    '''Send empty use srtp extension in TLSv1.2 hello'''
    pass

class UseSrtpNull12PFS(UseSrtpNull, NormalHandshake12PFS):
    '''Send empty use srtp extension in PFS TLSv1.2 hello'''
    pass

class UseSrtpOddLen(UseSrtpNull):
    '''Send use srtp extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension starts with a two byte length of two-byte elements
        # and the second array is optional with a simple binary string
        sock.send(self.make_use_srtp_hello(b'\x00\x05'
                                            b'\x00\x01\x00\x05\x00'
                                            b'\x00'))

class UseSrtpOddLen12(UseSrtpOddLen, NormalHandshake12):
    '''Send use srtp extension with too large length in TLSv1.2 hello'''
    pass


class UseSrtpOddLen12PFS(UseSrtpOddLen, NormalHandshake12PFS):
    '''Send use srtp extension with too large length in PFS TLSv1.2 hello'''
    pass


class UseSrtpOverflow(UseSrtpNull):
    '''Send use srtp extension with length larger than payload'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension has two arrays, one has a two byte length the other
        # a one byte length, make the first array longer than payload
        sock.send(self.make_use_srtp_hello(b'\x00\x06'
                                            b'\x00\x01\x00\x05'))


class UseSrtpOverflow12(UseSrtpOverflow, NormalHandshake12):
    '''Send use srtp extension with length larger than payload in TLSv1.2'''
    pass


class UseSrtpOverflow12PFS(UseSrtpOverflow, NormalHandshake12PFS):
    '''As in UseSrtpOverflow but in PFS TLSv1.2 hello'''
    pass


class HeartbeatNull(NormalHandshake):
    '''Send empty heartbeat extension in hello'''

    def make_heartbeat_hello(self, value):
        heartbeat_ext = Extension.create(
            extension_type=15,
            data=value)
        return self.make_hello([heartbeat_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension is a single byte value, don't include it
        sock.send(self.make_heartbeat_hello(b''))


class HeartbeatNull12(HeartbeatNull, NormalHandshake12):
    '''Send empty heartbeat extension in TLSv1.2 hello'''
    pass


class HeartbeatNull12PFS(HeartbeatNull, NormalHandshake12PFS):
    '''Send empty heartbeat extension in PFS TLSv1.2 hello'''
    pass


class HeartbeatInvalid(HeartbeatNull):
    '''Send heartbeat extension with invalid value in hello'''

    def test(self, sock):
        # the valid values are 1 and 2, send something else
        sock.send(self.make_heartbeat_hello(b'\x00'))


class HeartbeatInvalid12(HeartbeatInvalid, NormalHandshake12):
    '''Send heartbeat extension with invalid value in TLSv1.2 hello'''
    pass


class HeartbeatInvalid12PFS(HeartbeatInvalid, NormalHandshake12PFS):
    '''Send heartbeat extension with invalid value in PFS TLSv1.2 hello'''
    pass


class ALPNNull(NormalHandshake):
    '''Send empty ALPN extension in hello'''

    def make_alpn_hello(self, value):
        alpn_ext = Extension.create(
            extension_type=16,
            data=value)
        return self.make_hello([alpn_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension has an array, don't send anything
        sock.send(self.make_alpn_hello(b''))


class ALPNNull12(ALPNNull, NormalHandshake12):
    '''Send empty APLN extension in TLSv1.2 hello'''
    pass


class ALPNNull12PFS(ALPNNull, NormalHandshake12PFS):
    '''Send empty ALPN extension in PFS TLSv1.2 hello'''
    pass


class ALPNUnknown(ALPNNull):
    '''Send ALPN extension with only unknown protocol in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension is an array of arrays, the external array has
        # two byte length header, the internal arrays have one byte length
        sock.send(self.make_alpn_hello(b'\x00\x08'
                                        b'\x07unknown'))


class ALPNUnknown12(ALPNUnknown, NormalHandshake12):
    '''Send ALPN extension with only unknown protocol in TLSv1.2 hello'''
    pass


class ALPNUnknown12PFS(ALPNUnknown, NormalHandshake12PFS):
    '''Send ALPN extension with only unknown protocol in PFS TLSv1.2 hello'''
    pass


class ALPNOverflow(ALPNNull):
    '''Send ALPN extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension is an array of arrays, the external array has
        # two byte length header, the internal arrays have one byte length
        # make the external length too large
        sock.send(self.make_alpn_hello(b'\x00\x10'
                                        b'\x08http/1.1'))


class ALPNOverflow12(ALPNOverflow, NormalHandshake12):
    '''Send ALPN extension with too large length in TLSv1.2 hello'''
    pass


class ALPNOverflow12PFS(ALPNOverflow, NormalHandshake12PFS):
    '''Send ALPN extension with too large length in PFS TLSv1.2 hello'''
    pass


class OCSPv2Null(NormalHandshake):
    '''Send empty OCSPv2 staple extension in hello'''

    def make_ocspv2_hello(self, value):
        ocspv2_ext = Extension.create(
            extension_type=17,
            data=value)
        return self.make_hello([ocspv2_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal encoding has a list of complex items, don't include anything
        sock.send(self.make_ocspv2_hello(b''))


class OCSPv2Null12(OCSPv2Null, NormalHandshake12):
    '''Send empty OCSPv2 staple extension in TLSv1.2 hello'''
    pass


class OCSPv2Null12PFS(OCSPv2Null, NormalHandshake12PFS):
    '''Send empty OCSPv2 staple extension in PFS TLSv1.2 hello'''
    pass


class OCSPv2Overflow(OCSPv2Null):
    '''Send OCSPv2 staple extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        data = (b'\x00\x10'  # overall length of extension (too large)
                b'\x01'  # first request type (ocsp)
                b'\x00\x04'  # request length
                b'\x00\x00'  # responder ID list length
                b'\x00\x00'  # request extensions list length
                b'\x02'  # second request type (ocsp_multi)
                b'\x00\x04'  # request length
                b'\x00\x00'  # responder ID list length
                b'\x00\x00')  # request extensions list length
        sock.send(self.make_ocspv2_hello(data))


class OCSPv2Overflow12(OCSPv2Overflow, NormalHandshake12):
    '''Send OCSPv2 staple extension with too large length in TLSv1.2 hello'''
    pass


class OCSPv2Overflow12PFS(OCSPv2Overflow, NormalHandshake12PFS):
    '''As with OCSPv2Overflow but in PFS TLSv1.2 hello'''
    pass


class SignedCertTSNotNull(NormalHandshake):
    '''Send hello with signed certificate timestamp that is not empty'''

    def make_signed_cert_ts_hello(self, value):
        signed_cert_ts_ext = Extension.create(
            extension_type=18,
            data=value)
        return self.make_hello([signed_cert_ts_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension should be empty
        sock.send(self.make_signed_cert_ts_hello(b'\x04'))

class SignedCertTSNotNull12(SignedCertTSNotNull, NormalHandshake12):
    '''As with SignedCertTSNotNull but in TLSv1.2 hello'''
    pass


class SignedCertTSNotNull12PFS(SignedCertTSNotNull, NormalHandshake12PFS):
    '''As with SignedCertTSNotNull but in PFS TLSv1.2 hello'''
    pass


class ClientCertTypeNull(NormalHandshake):
    '''Send empty client certificate type extension in hello'''

    def make_client_cert_type_hello(self, value):
        client_cert_type_ext = Extension.create(
            extension_type=19,
            data=value)
        return self.make_hello([client_cert_type_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension has an array
        sock.send(self.make_client_cert_type_hello(b''))


class ClientCertTypeNull12(ClientCertTypeNull, NormalHandshake12):
    '''Send empty client certificate type extension in TLSv1.2 hello'''
    pass


class ClientCertTypeNull12PFS(ClientCertTypeNull, NormalHandshake12PFS):
    '''Send empty client certificate type extension in PFS TLSv1.2 hello'''
    pass


class ClientCertTypeOverflow(ClientCertTypeNull):
    '''Send client certificate type extension with too large length in hello'''

    def test(self, sock):
        logging.debug('sending Client Hello...')
        # first byte is the length of the array, send too large
        sock.send(self.make_client_cert_type_hello(b'\x04\x02\x01\x00'))


class ClientCertTypeOverflow12(ClientCertTypeOverflow, NormalHandshake12):
    '''As with ClientCertTypeOverflow, but in TLSv1.2 hello'''
    pass


class ClientCertTypeOverflow12PFS(ClientCertTypeOverflow,
                                  NormalHandshake12PFS):
    '''As with ClientCertTypeOverflow but in PFS TLSv1.2 hello'''
    pass


class ServerCertTypeNull(NormalHandshake):
    '''Send empty server certificate type extension in hello'''

    def make_server_cert_type_hello(self, value):
        server_cert_type_ext = Extension.create(
            extension_type=20,
            data=value)
        return self.make_hello([server_cert_type_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension has an array
        sock.send(self.make_server_cert_type_hello(b''))


class ServerCertTypeNull12(ServerCertTypeNull, NormalHandshake12):
    '''Send empty server certificate type extension in TLSv1.2 hello'''
    pass


class ServerCertTypeNull12PFS(ServerCertTypeNull, NormalHandshake12PFS):
    '''Send empty server certificate type extension in PFS TLSv1.2 hello'''
    pass


class ServerCertTypeOverflow(ServerCertTypeNull):
    '''Send server certificate type extension with too large length in hello'''

    def test(self, sock):
        logging.debug('sending Client Hello...')
        # first byte is the length of the array, send too large
        sock.send(self.make_server_cert_type_hello(b'\x04\x02\x01\x00'))


class ServerCertTypeOverflow12(ServerCertTypeOverflow, NormalHandshake12):
    '''As with ServerCertTypeOverflow, but in TLSv1.2 hello'''
    pass


class ServerCertTypeOverflow12PFS(ServerCertTypeOverflow,
                                  NormalHandshake12PFS):
    '''As with ServerCertTypeOverflow but in PFS TLSv1.2 hello'''
    pass


class PaddingNull(NormalHandshake):
    '''Send empty padding extension in hello'''

    def make_padding_hello(self, value):
        padding_ext = Extension.create(
            extension_type=21,
            data=value)
        return self.make_hello([padding_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # there is no invalid encoding of extension, send an empty one
        sock.send(self.make_padding_hello(b''))


class PaddingNull12(PaddingNull, NormalHandshake12):
    '''Send empty padding extension in TLSv1.2 hello'''
    pass


class PaddingNull12PFS(PaddingNull, NormalHandshake12PFS):
    '''Send empty padding extension in PFS TLSv1.2 hello'''
    pass


class Padding300Byte(PaddingNull):
    '''Use padding extension to send 300 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (300 - (64 - 5) - 4)))


class Padding300Byte12(PaddingNull, NormalHandshake12):
    '''Use padding extension to send 300 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (300 - (88 - 5) - 4)))


class Padding300Byte12PFS(PaddingNull, NormalHandshake12PFS):
    '''Use padding extension to send 300 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (300 - (144 - 5) - 4)))


class Padding600Byte(PaddingNull):
    '''Use padding extension to send 600 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (600 - (64 - 5) - 4)))


class Padding600Byte12(PaddingNull, NormalHandshake12):
    '''Use padding extension to send 600 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (600 - (88 - 5) - 4)))


class Padding600Byte12PFS(PaddingNull, NormalHandshake12PFS):
    '''Use padding extension to send 600 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (600 - (144 - 5) - 4)))


class Padding16384Byte(PaddingNull):
    '''Use padding extension to send 16384 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        # 16384 is the largest size that can be sent in a single record layer
        sock.send(self.make_padding_hello(b'\x00' * (16384 - (64 - 5) - 4)))


class Padding16384Byte12(PaddingNull, NormalHandshake12):
    '''Use padding extension to send 16384 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16384 - (88 - 5) - 4)))


class Padding16384Byte12PFS(PaddingNull, NormalHandshake12PFS):
    '''Use padding extension to send 16384 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16384 - (144 - 5) - 4)))


class Padding16385Byte(Probe):
    '''Use padding extension to send 16385 byte large hello'''

    def __init__(self):
        super(Padding16385Byte, self).__init__()
        self.hello_version = TLSRecord.TLS1_0
        self.ciphers = DEFAULT_CIPHERS

    def make_padding_hello(self, value):
        padding_ext = Extension.create(
            extension_type=21,
            data=value)
        RECORD_MAX=16384
        hello = ClientHelloMessage.create(self.hello_version,
                                          b'01234567890123456789012345678901',
                                          self.ciphers,
                                          extensions=[padding_ext])
        hello_bytes = hello.bytes
        records = [TLSRecord.create(content_type=TLSRecord.Handshake,
                                    version=TLSRecord.TLS1_0,
                                    message=hello_bytes[i:i+RECORD_MAX]).bytes
                   for i in range(0, len(hello_bytes), RECORD_MAX)]
        return b''.join(records)

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16385 - (64 - 5) - 4)))


class Padding16385Byte12(Padding16385Byte):
    '''Use padding extension to send 16385 byte large TLSv1.2 hello'''

    def __init__(self):
        super(Padding16385Byte, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_12_CIPHERS

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16385 - (88 - 5) - 4)))


class Padding16385Byte12PFS(Padding16385Byte):
    '''Use padding extension to send 16385 byte large PFS TLSv1.2 hello'''

    def __init__(self):
        super(Padding16385Byte, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_PFS_CIPHERS

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16385 - (144 - 5) - 4)))


class Padding16387Byte(Padding16385Byte):
    '''Use padding extension to send 16387 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16387 - (64 - 5) - 4)))


class Padding16387Byte12(Padding16385Byte12):
    '''Use padding extension to send 16387 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16387 - (88 - 5) - 4)))


class Padding16387Byte12PFS(Padding16385Byte12PFS):
    '''Use padding extension to send 16387 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16387 - (144 - 5) - 4)))


class Padding16389Byte(Padding16385Byte):
    '''Use padding extension to send 16389 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16389 - (64 - 5) - 4)))


class Padding16389Byte12(Padding16385Byte12):
    '''Use padding extension to send 16389 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16389 - (88 - 5) - 4)))


class Padding16389Byte12PFS(Padding16385Byte12PFS):
    '''Use padding extension to send 16389 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16389 - (144 - 5) - 4)))


class Padding17520Byte(Padding16385Byte):
    '''Use padding extension to send 17520 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (17520 - (64 - 5) - 4)))


class Padding17520Byte12(Padding16385Byte12):
    '''Use padding extension to send 17520 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (17520 - (88 - 5) - 4)))


class Padding17520Byte12PFS(Padding16385Byte12PFS):
    '''Use padding extension to send 17520 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (17520 - (144 - 5) - 4)))


class EtMNotNull(NormalHandshake):
    '''Send not empty encrypt then mac extension in hello'''

    def make_etm_hello(self, value):
        etm_ext = Extension.create(
            extension_type=22,
            data=value)
        return self.make_hello([etm_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must be empty
        sock.send(self.make_etm_hello(b'\x04'))


class EtMNotNull12(EtMNotNull, NormalHandshake12):
    '''Send not empty encrypt then mac extension in TLSv1.2 hello'''
    pass


class EtMNotNull12PFS(EtMNotNull, NormalHandshake12PFS):
    '''Send not empty encrypt then mac extension in PFS TLSv1.2 hello'''
    pass


class EMSNotNull(NormalHandshake):
    '''Send not empty extended master secret extension in hello'''

    def make_ems_hello(self, value):
        ems_ext = Extension.create(
            extension_type=23,
            data=value)
        return self.make_hello([ems_ext])


    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must be empty
        sock.send(self.make_ems_hello(b'\x04'))


class EMSNotNull12(EMSNotNull, NormalHandshake12):
    '''Send not empty extended master secret extension in TLSv1.2 hello'''
    pass


class EMSNotNull12PFS(EMSNotNull, NormalHandshake12PFS):
    '''Send not empty extended master secret extension in PFS TLSv1.2 hello'''
    pass


class CachedInfoNull(NormalHandshake):
    '''Send empty cached info extension in hello'''

    def make_cached_info_hello(self, value):
        cached_info_ext = Extension.create(
            extension_type=25,
            data=value)
        return self.make_hello([cached_info_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must include an array of complex objects
        sock.send(self.make_cached_info_hello(b''))


class CachedInfoNull12(CachedInfoNull, NormalHandshake12):
    '''Send empty cached info extension in TLSv1.2 hello'''
    pass


class CachedInfoNull12PFS(CachedInfoNull, NormalHandshake12PFS):
    '''Send empty cached info extension in PFS TLSv1.2 hello'''
    pass


class CachedInfoOverflow(CachedInfoNull):
    '''Send cached info extension with invalid size in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first two bytes are the size of the array, send too large one
        sock.send(self.make_cached_info_hello(b'\x00\x44'
                                               b'\x02'  # type cert_req
                                               b'\x20' +  # length of hash
                                               b'\xaf' * 32))  # hash


class CachedInfoOverflow12(CachedInfoOverflow, NormalHandshake12):
    '''Send cached info extension with invalid size in TLSv1.2 hello'''
    pass


class CachedInfoOverflow12PFS(CachedInfoOverflow, NormalHandshake12PFS):
    '''Send cached info extension with invalid size in PFS TLSv1.2 hello'''
    pass


class SessionTicketNull(NormalHandshake):
    '''Send empty session ticket extension in hello'''

    def make_session_ticket_hello(self, value):
        session_ticket_ext = Extension.create(
            extension_type=35,
            data=value)
        return self.make_hello([session_ticket_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first two bytes of the extension are the length, don't include any
        sock.send(self.make_session_ticket_hello(b''))


class SessionTicketNull12(SessionTicketNull, NormalHandshake12):
    '''Send empty session ticket extension in TLSv1.2 hello'''
    pass


class SessionTicketNull12PFS(SessionTicketNull, NormalHandshake12PFS):
    '''Send empty session ticket extension in PFS TLSv1.2 hello'''
    pass


class SessionTicketOverflow(SessionTicketNull):
    '''Send session ticket extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first two bytes are the length, send too large one
        sock.send(self.make_session_ticket_hello(b'\x02\x00' +
                                                  b'\xe7' * 0xff))


class SessionTicketOverflow12(SessionTicketOverflow, NormalHandshake12):
    '''Send session ticket extension with too large length in TLSv1.2 hello'''
    pass


class SessionTicketOverflow12PFS(SessionTicketOverflow, NormalHandshake12PFS):
    '''Send session ticket ext with too large length in PFS TLSv1.2 hello'''
    pass


class NPNNotNull(NormalHandshake):
    '''Send non empty NPN extension in hello'''

    def make_npn_hello(self, value):
        npn_ext = Extension.create(
            extension_type=13172,
            data=value)
        return self.make_hello([npn_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has to be empty
        sock.send(self.make_npn_hello(b'\x04'))


class NPNNotNull12(NPNNotNull, NormalHandshake12):
    '''Send non empty NPN extension in TLSv1.2 hello'''
    pass


class NPNNotNull12PFS(NPNNotNull, NormalHandshake12PFS):
    '''Send non empty NPN extension in PFS TLSv1.2 hello'''
    pass


class TACKNotNull(NormalHandshake):
    '''Send not empty TACK extension in hello'''

    def make_tack_hello(self, value):
        tack_ext = Extension.create(
            extension_type=62208,
            data=value)
        return self.make_hello([tack_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must be empty
        sock.send(self.make_tack_hello(b'\x08'))


class TACKNotNull12(TACKNotNull, NormalHandshake12):
    '''Send not empty TACK extension in TLSv1.2 hello'''
    pass


class TACKNotNull12PFS(TACKNotNull, NormalHandshake12PFS):
    '''Send not empty TACK extension in PFS TLSv1.2 hello'''
    pass

#!/usr/bin/python

import socket
import errno
import logging
import os
import platform

if platform.system() != 'Java':
    from select import select
else:
    from select import cpython_compatible_select as select

# Disable socks support in Jython
if platform.system() != 'Java':
    import socks
else:
    if 'socks_proxy' in os.environ:
        logging.warn('Unable to honour socks_proxy environment variable, unsupported in Jython')

from prober_utils import *

settings = {
    # Note that changing these will invalidate many of the fingerprints
    'default_hello_version': TLSRecord.TLS1_0,
    'default_record_version': TLSRecord.TLS1_0,
    'socket_timeout': 5
}

class Probe(object):

    #
    # Reusable standard elements
    #
    def __init__(self):
        self.ipaddress = None

    def connect(self, ipaddress, port, starttls_mode):
        self.ipaddress = ipaddress
        # Check if we're using socks
        if 'socks_proxy' in os.environ:
            socks_host, socks_port = os.environ['socks_proxy'].split(':')
            s = socks.socksocket()
            s.setproxy(socks.PROXY_TYPE_SOCKS5, socks_host, int(socks_port))
        else:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        s.settimeout(settings['socket_timeout'])
        s.connect((ipaddress, port))

        # Do starttls if relevant
        starttls(s, port, starttls_mode)

        # return s.makefile('rw', 0)
        return s

    def test(self, sock):
        pass

    def process_response(self, sock):

        response = ''
        got_done = False

        while True:
            # Check if there is anything following the server done
            if got_done:
                # If no data then we're done (the server hasn't sent anything further)
                # we allow 500ms to give the followup time to arrive
                if not select([sock.fileno(),],[],[],0.5)[0]:
                    break

            try:
                record = read_tls_record(sock)
                response += '*(%x)' % record.version() # TODO: Not sure that recording the record layer version is worth it?
            except socket.timeout as e:
                response += 'error:timeout'
                break
            except socket.error as e:
                # response += 'error:%s|' % errno.errorcode[e.errno]
                response += 'error:%s' % e
                break
            except IOError as e:
                response += 'error:%s|' % str(e)
                break

            if record.content_type() == TLSRecord.Handshake:
                # A single handshake record can contain multiple handshake messages
                processed_bytes = 0
                while processed_bytes < record.message_length():
                    message = HandshakeMessage.from_bytes(record.message()[processed_bytes:])

                    if message.message_type() == message.ServerHello:
                        response += 'handshake:%s(%x)|' % (message.message_types[message.message_type()], message.server_version())
                    else:
                        response += 'handshake:%s|' % (message.message_types[message.message_type()])

                    if message.message_type() == HandshakeMessage.ServerHelloDone:
                        got_done = True

                    processed_bytes += message.message_length() + 4

                if got_done:
                    continue

            elif record.content_type() == TLSRecord.Alert:
                alert = AlertMessage.from_bytes(record.message())

                if alert.alert_level() == AlertMessage.Fatal:
                    response += 'alert:%s:fatal|' % alert.alert_types[alert.alert_type()]
                    break
                else:
                    response += 'alert:%s:warning|' % alert.alert_types[alert.alert_type()]
            else:
                if record.content_type() in record.content_types:
                    response += 'record:%s|' % record.content_types[record.content_type()]
                else:
                    response += 'record:type(%x)|' % record.content_type()

            if got_done:
                break

        return response

    def probe(self, ipaddress, port, starttls):
        sock = self.connect(ipaddress, port, starttls)
        try:
            result = self.test(sock)
        except socket.timeout as e:
            result = 'writeerror:timeout'
            try:
                sock.shutdown(socket.SHUT_RD_WR)
            except:
                pass
            sock.close()
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            try:
                sock.shutdown(socket.SHUT_RD_WR)
            except:
                pass
            sock.close()
            return result

        if result:
            return result
        result = self.process_response(sock)
        try:
            sock.shutdown(socket.SHUT_RD_WR)
        except:
            pass
        sock.close()
        return result


class NormalHandshake(Probe):
    '''A normal handshake'''

    def __init__(self):
        super(NormalHandshake, self).__init__()
        self.make_hello = make_hello

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())


class NormalHandshakePFS(NormalHandshake):
    '''Normal handshake with PFS ciphersuites'''

    def __init__(self):
        super(NormalHandshakePFS, self).__init__()
        self.make_hello = make_pfs_hello


class NormalHandshake11(NormalHandshake):
    '''Normal TLSv1.1 handshake'''

    def __init__(self):
        super(NormalHandshake11, self).__init__()
        self.make_hello = make_11_hello


class NormalHandshake11PFS(NormalHandshake):
    '''Normal TLSv1.1 handshake'''

    def __init__(self):
        super(NormalHandshake11PFS, self).__init__()
        self.make_hello = make_11_pfs_hello


class NormalHandshake12(NormalHandshake):
    '''Normal TLSv1.2 handshake'''

    def __init__(self):
        super(NormalHandshake12, self).__init__()
        self.make_hello = make_12_hello


class NormalHandshake12PFS(NormalHandshake):
    '''Normal TLSv1.2 handshake with PFS ciphersuites'''

    def __init__(self):
        super(NormalHandshake12PFS, self).__init__()
        self.make_hello = make_12_pfs_hello


class NormalHandshake12PFSw13(Probe):
    '''TLSv1.2 with PFS ciphers with a TLSv1.3 version (invalid TLSv1.3)'''

    def make_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_3,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_PFS_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())

class ValidSessionID(Probe):
    '''Send session ID that is too long'''

    def __init__(self):
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = MAX_CIPHERS

    def make_hello_payload(self, version, cipher_suites):
        session_id = b'0123456789' # session ID is up to 32 bytes long
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             len(session_id)) +
                 session_id + ciphers + b'\x01\x00' + b'\x00\x00')

        return hello

    def make_hello(self, version, cipher_suites):
        hello = self.make_hello_payload(version, cipher_suites)

        hello_msg = HandshakeMessage.create(HandshakeMessage.ClientHello,
                                            hello)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_2,
                                  message=hello_msg.bytes)
        return record.bytes

    def generatePacket(self):
        return self.make_hello(self.hello_version, self.ciphers)

    def test(self, sock):
        logging.debug('Sending Client Helo...')
        sock.send(self.make_hello(self.hello_version, self.ciphers))

class InvalidSessionID(Probe):
    '''Send session ID that is too long'''

    def __init__(self):
        self.hello_version = TLSRecord.TLS1_0
        self.ciphers = DEFAULT_CIPHERS

    def make_hello_payload(self, version, cipher_suites):
        session_id = b'0123456789' * 4  # session ID is up to 32 bytes long
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             len(session_id)) +
                 session_id + ciphers + b'\x01\x00' + b'\x00\x00')

        return hello

    def make_hello(self, version, cipher_suites):
        hello = self.make_hello_payload(version, cipher_suites)

        hello_msg = HandshakeMessage.create(HandshakeMessage.ClientHello,
                                            hello)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=hello_msg.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Helo...')
        sock.send(self.make_hello(self.hello_version, self.ciphers))


class InvalidSessionID12(InvalidSessionID):
    '''Send session ID that is too long in TLSv1.2 hello'''

    def __init__(self):
        super(InvalidSessionID12, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_12_CIPHERS


class InvalidSessionID12PFS(InvalidSessionID):
    '''Send session ID that is too long in PFS TLSv1.2 hello'''

    def __init__(self):
        super(InvalidSessionID12PFS, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_PFS_CIPHERS


class InvalidCiphersLength(InvalidSessionID):
    '''Send client hello with length field of ciphers that is invalid (odd)'''

    def make_hello_payload(self, version, cipher_suites):
        cipher_bytes = struct.pack('>{0}H'.format(len(cipher_suites)),
                                   *cipher_suites) + b'\x00'
        ciphers = struct.pack('>H', len(cipher_bytes)) + cipher_bytes
        hello = (struct.pack('>H32sB', version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x01\x00' + b'\x00\x00')

        return hello


class InvalidCiphersLength12(InvalidCiphersLength, InvalidSessionID12):
    '''As with InvalidCiphersLength but with TLSv1.2 helo'''
    pass


class InvalidCiphersLength12PFS(InvalidCiphersLength, InvalidSessionID12PFS):
    '''As with InvalidCiphersLength but with PFS TLSv1.2 hello'''
    pass


class InvalidExtLength(InvalidSessionID):
    '''Send client hello with length of extensions filed truncated'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x01\x00' + b'\x00')

        return hello


class InvalidExtLength12(InvalidExtLength, InvalidSessionID12):
    '''As with InvalidExtLength but in TLSv1.2 hello'''
    pass


class InvalidExtLength12PFS(InvalidExtLength, InvalidSessionID12PFS):
    '''As with InvalidExtLength but in PFS TLSv1.2 hello'''
    pass


class ExtensionsUnderflow(InvalidSessionID):
    '''Send hello with data length lower than stated size'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x01\x00'
                 b'\x00\x01'  # extensions length, just one byte
                 b'\xff\x01'  # extension ID - secure renego indication
                 b'\x00\x01'  # secure renego indication ext length
                 b'\x00')  # valid payload for extension

        return hello


class ExtensionsUnderflow12(ExtensionsUnderflow, InvalidSessionID12):
    '''As in ExtensionsUnderflow but in TLSv1.2 hello'''
    pass


class ExtensionsUnderflow12PFS(ExtensionsUnderflow, InvalidSessionID12PFS):
    '''As in ExtensionsUnderflow but in PFS TLSv1.2 hello'''
    pass


class EmptyCompression(InvalidSessionID):
    '''Send hello with no compression methods'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x00' + b'\x00\x00')

        return hello


class EmptyCompression12(EmptyCompression, InvalidSessionID12):
    '''As with EmptyCompression but in TLSv1.2 hello'''
    pass


class EmptyCompression12PFS(EmptyCompression, InvalidSessionID12PFS):
    '''As with EmptyCompression but in PFS TLSv1.2 hello'''
    pass


class CompressOnly(InvalidSessionID):
    '''Send hello with no support for uncompressed communication'''

    def make_hello_payload(self, version, cipher_suites):
        ciphers = struct.pack('>H{0}H'.format(len(cipher_suites)),
                              len(cipher_suites) * 2, *cipher_suites)
        hello = (struct.pack('>H32sB',
                             version,
                             b'01234567890123456789012345678901',
                             0) +
                 ciphers + b'\x02\x01\x40' + b'\x00\x00')

        return hello


class CompressOnly12(CompressOnly, InvalidSessionID12):
    '''As with CompressOnly but in TLSv1.2 hello'''
    pass


class CompressOnly12PFS(CompressOnly, InvalidSessionID12PFS):
    '''As with CompressOnly but in PFS TLSv1.2 hello'''
    pass


class DoubleClientHello(NormalHandshake):
    '''Two client hellos'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())


class DoubleClientHello12(DoubleClientHello, NormalHandshake12):
    '''Two client hellos, TLSv1.2'''
    pass


class DoubleClientHello12PFS(DoubleClientHello, NormalHandshake12PFS):
    '''Two client hellos, TLSv1.2 w/PFS ciphers'''
    pass


class ChangeCipherSpec(NormalHandshake):
    '''Send a hello then change cipher spec'''

    def __init__(self):
        super(ChangeCipherSpec, self).__init__()
        self.make_ccs = make_ccs
        self.record_version = TLSRecord.TLS1_0

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending ChangeCipherSpec...')
        sock.send(self.make_ccs(self.record_version))


class ChangeCipherSpec12(ChangeCipherSpec, NormalHandshake12):
    '''Send TLSv1.2 hello then change cipher spec'''

    def __init__(self):
        super(ChangeCipherSpec12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class ChangeCipherSpec12PFS(NormalHandshake12PFS, ChangeCipherSpec12):
    '''Send PFS TLSv1.2 hello then change cipher spec'''
    pass


class HelloRequest(NormalHandshake):
    '''Send a hello then hello request'''

    def __init__(self):
        super(HelloRequest, self).__init__()
        self.make_hello_request = make_hello_request
        self.record_version = TLSRecord.TLS1_0

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending Hello Request...')
        sock.send(self.make_hello_request(self.record_version))


class HelloRequest12(HelloRequest, NormalHandshake12):
    '''Send a TLSv1.2 hello then hello request'''

    def __init__(self):
        super(HelloRequest12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class HelloRequest12PFS(NormalHandshake12PFS, HelloRequest12):
    '''Send a PFS TLSv1.2 hello then hello request'''
    pass


class EmptyChangeCipherSpec(NormalHandshake):
    '''Send a hello then an empty change cipher spec'''

    def __init__(self):
        super(EmptyChangeCipherSpec, self).__init__()
        self.record_version = TLSRecord.TLS1_0

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())
        logging.debug('Sending Empty ChangeCipherSpec...')

        record = TLSRecord.create(content_type=TLSRecord.ChangeCipherSpec,
                                  version=self.record_version,
                                  message='')
        sock.send(record.bytes)


class EmptyChangeCipherSpec12(EmptyChangeCipherSpec, NormalHandshake12):
    '''Send TLSv1.2 hello then an empty change cipher spec'''

    def __init__(self):
        super(EmptyChangeCipherSpec12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class EmptyChangeCipherSpec12PFS(NormalHandshake12PFS,
                                 EmptyChangeCipherSpec12):
    '''Send PFS TLSv1.2 hello then an empty change cipher spec'''
    pass


class BadHandshakeMessage(Probe):
    '''An invalid handshake message'''

    def make_bad_handshake(self):
        content = 'Something'

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=content)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(make_hello())
        logging.debug('Sending bad handshake message...')
        sock.send(self.make_bad_handshake())


class OnlyECCipherSuites(Probe):
    '''Try connecting with ECC cipher suites only'''

    def make_ec_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_0,
                                          b'01234567890123456789012345678901',
                                          [TLS_ECDH_RSA_WITH_RC4_128_SHA,
                                           TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
                                           TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
                                           TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
                                           TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                                           TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                                           TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256])

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=TLSRecord.TLS1_0,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_ec_hello())


class Heartbeat(NormalHandshake):
    '''Try to send a heartbeat message'''

    def __init__(self):
        super(Heartbeat, self).__init__()
        self.record_version = TLSRecord.TLS1_0

    def make_hb_hello(self):
        hb_extension = HeartbeatExtension.create()
        return self.make_hello([hb_extension])

    def make_heartbeat(self):
        heartbeat = HeartbeatMessage.create(HeartbeatMessage.HeartbeatRequest,
                                            'XXXX')

        record = TLSRecord.create(content_type=TLSRecord.Heartbeat,
                                  version=self.record_version,
                                  message=heartbeat.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hb_hello())
        logging.debug('Sending Heartbeat...')
        sock.send(self.make_heartbeat())


class Heartbeat12(NormalHandshake12, Heartbeat):
    '''Try to send a heartbeat message in TLSv1.2 connection'''

    def __init__(self):
        super(Heartbeat12, self).__init__()
        self.record_version = TLSRecord.TLS1_2


class Heartbeat12PFS(NormalHandshake12PFS, Heartbeat12):
    '''Try to send a hearbeat message in PFS TLSv1.2 connection'''
    pass


class Heartbleed(Heartbeat):
    '''Try to send a heartbleed attack'''

    def make_heartbeat(self):
        heartbeat = HeartbeatMessage.create(HeartbeatMessage.HeartbeatRequest,
                                            'XXXX', 0x4000)

        record = TLSRecord.create(content_type=TLSRecord.Heartbeat,
                                  version=self.record_version,
                                  message=heartbeat.bytes)

        #hexdump(record.bytes)
        return record.bytes


class Heartbleed12(Heartbeat12, Heartbleed):
    '''Try to send a heartbleed attack in TLSv1.2'''
    pass


class Heartbleed12PFS(Heartbeat12PFS, Heartbleed):
    '''Try to send a heartbleed attack in TLSv1.2'''
    pass


class HighTLSVersion(Probe):
    '''Set a high TLS version in the record'''

    def make_hello(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)
        return hello

    def make_high_tls_hello(self):
        hello = self.make_hello()

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=0x400,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_high_tls_hello())


class HighTLSVersion12(HighTLSVersion):
    '''Set a high TLS version in the record of TLSv1.2 hello'''

    def make_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_12_CIPHERS)
        return hello


class HighTLSVersion12PFS(HighTLSVersion):
    '''Set a high TLS version in the record of PFS TLSv1.2 hello'''

    def make_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_PFS_CIPHERS)
        return hello


class VeryHighTLSVersion(HighTLSVersion):
    '''Set a very high TLS version in the record'''

    def make_high_tls_hello(self):
        hello = self.make_hello()

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=0xffff,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes


class VeryHighTLSVersion12(HighTLSVersion12, VeryHighTLSVersion):
    '''Set a very high TLS version in the record of TLSv1.2 hello'''
    pass


class VeryHighTLSVersion12PFS(HighTLSVersion12PFS, VeryHighTLSVersion):
    '''Set a very high TLS version in the record of PFS TLSv1.2 hello'''
    pass


class ZeroTLSVersion(HighTLSVersion):
    '''Set a zero version in the record'''

    def make_high_tls_hello(self):
        hello = self.make_hello()

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=0x000,
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes


class ZeroTLSVersion12(HighTLSVersion12, ZeroTLSVersion):
    '''Set a zero version in the record of TLSv1.2 hello'''
    pass


class ZeroTLSVersion12PFS(HighTLSVersion12PFS, ZeroTLSVersion):
    '''Set a zero version in the record of PFS TLSv1.2 hello'''
    pass


class HighHelloVersion(Probe):
    '''Set a high version in the hello'''

    def __init__(self):
        super(HighHelloVersion, self).__init__()
        self.hello_version = 0x400
        self.hello_ciphers = DEFAULT_CIPHERS

    def make_high_tls_hello(self):
        hello = ClientHelloMessage.create(self.hello_version,
                                          b'01234567890123456789012345678901',
                                          self.hello_ciphers)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_high_tls_hello())


class HighHelloVersionNew(HighHelloVersion):
    '''Set a high version in a hello with more ciphers'''

    def __init__(self):
        super(HighHelloVersionNew, self).__init__()
        self.hello_ciphers = DEFAULT_12_CIPHERS


class HighHelloVersionPFS(HighHelloVersion):
    '''Set a high version in a hello with PFS ciphers'''

    def __init__(self):
        super(HighHelloVersionPFS, self).__init__()
        self.hello_ciphers = DEFAULT_PFS_CIPHERS


class VeryHighHelloVersion(HighHelloVersion):
    '''Set a very high version in the hello'''

    def __init__(self):
        super(VeryHighHelloVersion, self).__init__()
        self.hello_version = 0xffff


class VeryHighHelloVersionNew(HighHelloVersionNew, VeryHighHelloVersion):
    '''Set a very high version in the hello with more ciphers'''
    pass


class VeryHighHelloVersionPFS(HighHelloVersionPFS, VeryHighHelloVersion):
    '''Set a very high version in the hello with PFS ciphers'''
    pass


class ZeroHelloVersion(Probe):
    '''Set a zero version in the hello'''

    def make_zero_tls_hello(self):
        hello = ClientHelloMessage.create(0x000,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_zero_tls_hello())


class BadContentType(Probe):
    '''Use an invalid content type in the record'''

    def make_bad_content_type(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=17,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_bad_content_type())


class RecordLengthOverflow(Probe):
    '''Make the record length exceed the stated one'''

    def make_record_length_overflow(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes,
                                  length=0x0001)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_record_length_overflow())


class RecordLengthUnderflow(Probe):
    '''Make the record shorter than the specified length'''

    def make_record_length_underflow(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes,
                                  length=0xffff)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        try:
            sock.send(self.make_record_length_underflow())
        except socket.timeout as e:
            result = 'writeerror:timeout'
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            return result


class EmptyRecord(NormalHandshake):
    '''Send an empty record then the hello'''

    def make_empty_record(self):
        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message='')

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending empty record...')
        sock.send(self.make_empty_record())
        logging.debug('Sending Client Hello...')
        sock.send(self.make_hello())


class EmptyRecord12(NormalHandshake12, EmptyRecord):
    '''Send an empty record then TLSv1.2 hello'''
    pass


class EmptyRecord12PFS(NormalHandshake12PFS, EmptyRecord):
    '''Send and empty record then PFS TLSv1.2 hello'''
    pass


class TwoInvalidPackets(Probe):
    '''Send two invalid messages'''

    def test(self, sock):
        logging.debug('Sending split hello...')
        part_one = b'<tls.record.TLSRecord object at 0x7fd2dc0906d0>'
        part_two = b'<tls.record.TLSRecord object at 0x7fd2dc090690>'
        sock.send(part_one)
        try:
            sock.send(part_two)
        except socket.timeout as e:
            result = 'writeerror:timeout'
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            return result


class SplitHelloRecords(Probe):
    '''Split the hello over two records'''

    def make_split_hello(self):
        hello = ClientHelloMessage.create(settings['default_hello_version'],
                                          b'01234567890123456789012345678901',
                                          DEFAULT_CIPHERS)

        first = hello.bytes[:10]
        second = hello.bytes[10:]

        record_one = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=first)
        record_two = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=0x301,
                                      message=second)

        #hexdump(record.bytes)
        return record_one.bytes, record_two.bytes

    def test(self, sock):
        logging.debug('Sending split hello...')
        part_one, part_two = self.make_split_hello()
        sock.send(part_one)
        try:
            sock.send(part_two)
        except socket.timeout as e:
            result = 'writeerror:timeout'
            return result
        except socket.error as e:
            result = 'writeerror:%s|' % errno.errorcode[e.errno]
            return result


class SplitHelloRecords12(SplitHelloRecords):
    '''Split the TLS1.2 hello over two records'''

    def make_split_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_12_CIPHERS)

        first = hello.bytes[:10]
        second = hello.bytes[10:]

        record_one = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=first)
        record_two = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=second)

        #hexdump(record.bytes)
        return record_one.bytes, record_two.bytes


class SplitHelloRecords12PFS(SplitHelloRecords):
    '''Split the TLS1.2 PFS hello over two records'''

    def make_split_hello(self):
        hello = ClientHelloMessage.create(TLSRecord.TLS1_2,
                                          b'01234567890123456789012345678901',
                                          DEFAULT_PFS_CIPHERS)

        first = hello.bytes[:10]
        second = hello.bytes[10:]

        record_one = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=first)
        record_two = TLSRecord.create(content_type=TLSRecord.Handshake,
                                      version=settings['default_record_version'],
                                      message=second)

        #hexdump(record.bytes)
        return record_one.bytes, record_two.bytes


class SplitHelloPackets(NormalHandshake):
    '''Split the hello over two packets'''

    def test(self, sock):
        logging.debug('Sending Client Hello part one...')
        record = self.make_hello()
        sock.send(record[:10])
        # sock.flush()
        logging.debug('Sending Client Hello part two...')
        sock.send(record[10:])


class SplitHelloPackets12(SplitHelloPackets, NormalHandshake12):
    '''Split the TLS1.2 hello over two packets'''
    pass


class SplitHelloPackets12PFS(SplitHelloPackets, NormalHandshake12PFS):
    '''Split the TLS1.2 PFS hello over two packets'''
    pass


class NoCiphers(Probe):
    '''Send an empty cipher list'''

    def __init__(self):
        super(NoCiphers, self).__init__()
        self.hello_version = settings['default_hello_version']

    def make_no_ciphers_hello(self):
        hello = ClientHelloMessage.create(self.hello_version,
                                          b'01234567890123456789012345678901',
                                          [])

        record = TLSRecord.create(content_type=TLSRecord.Handshake,
                                  version=settings['default_record_version'],
                                  message=hello.bytes)

        #hexdump(record.bytes)
        return record.bytes

    def test(self, sock):
        logging.debug('Sending No ciphers Hello...')
        sock.send(self.make_no_ciphers_hello())


class NoCiphers12(NoCiphers):
    '''Send and empty cipher list in TLSv1.2 hello'''

    def __init__(self):
        super(NoCiphers12, self).__init__()
        self.hello_version = TLSRecord.TLS1_2


class SNIWrongName(NormalHandshake):
    '''Send a server name indication for a non-matching name'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(name)
        return self.make_hello([sni_extension])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello('thisisnotyourname'))


class SNIWrongName12(NormalHandshake12, SNIWrongName):
    '''Send a server name indication for non-matching name in TLSv1.2 hello'''
    pass


class SNIWrongName12PFS(NormalHandshake12PFS, SNIWrongName):
    '''Send a SNI extension for non-matching name in PFS TLSv1.2 hello'''
    pass


class SNILongName(SNIWrongName):
    '''Send a server name indication with a long name'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello('x'*500))


class SNILongName12(NormalHandshake12, SNILongName):
    '''Send a server name indication with a long name in TLSv1.2 hello'''
    pass


class SNILongName12PFS(NormalHandshake12PFS, SNILongName):
    '''Send a server name indication with a long name in PFS TLSv1.2 hello'''
    pass


class SNIEmptyName(SNIWrongName):
    '''Send a server name indication with an empty name'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello(''))


class SNIEmptyName12(NormalHandshake12, SNIEmptyName):
    '''Send a server name indication with an empty name in TLSv1.2 hello'''
    pass


class SNIEmptyName12PFS(NormalHandshake12PFS, SNIEmptyName):
    '''Send a server name indication with an empty name in PFS TLSv1.2 hello'''
    pass


class SNIOneWrong(NormalHandshake):
    '''Send server name indication with two names, one wrong'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(None,
                                                   (name, 'thisisnotyourname'))
        record = self.make_hello([sni_extension])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello(self.ipaddress))


class SNIOneWrong12(SNIOneWrong, NormalHandshake12):
    '''Send server name indication with two names, one wrong in TLS1.2 hello'''
    pass


class SNIOneWrong12PFS(SNIOneWrong, NormalHandshake12PFS):
    '''As in SNIOneWrong but in PFS TLS1.2 hello'''
    pass


class SNIWithDifferentType(NormalHandshake):
    '''Send server name indication with two names, one not of host_name type'''

    def make_sni_ext(self, server_names):
        encoded_names = b''.join(struct.pack('!BH', name_type, len(name))
                                + str.encode(name) for name_type, name in server_names)
        ext_data = struct.pack('!H', len(encoded_names)) + encoded_names
        return Extension.create(extension_type=Extension.ServerName,
                                data=ext_data)

    def make_sni_hello(self, server_names):
        sni_extension = self.make_sni_ext(server_names)

        record = self.make_hello([sni_extension])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        server_names = []
        server_names += [(ServerNameExtension.HostName, self.ipaddress)]
        # only type 0 (HostName) is defined, any other should be ignored
        server_names += [(4, '<binary-data>')]

        sock.send(self.make_sni_hello(server_names))


class SNIWithDifferentType12(SNIWithDifferentType, NormalHandshake12):
    '''As with SNIWithDifferentType but in TLSv1.2 hello'''
    pass


class SNIWithDifferentType12PFS(SNIWithDifferentType, NormalHandshake12PFS):
    '''As with SNIWithDifferentType but in PFS TLSv1.2 hello'''
    pass


class SNIDifferentTypeRev(SNIWithDifferentType):
    '''Send hello like in SNIWithDifferentType but reverse order of names'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        server_names = []
        # only type 0 (HostName) is defined, any other should be ignored
        server_names += [(4, '<binary-data>')]
        server_names += [(ServerNameExtension.HostName, self.ipaddress)]

        sock.send(self.make_sni_hello(server_names))


class SNIDifferentTypeRev12(SNIDifferentTypeRev, NormalHandshake12):
    '''As with SNIDifferentTypeRev but in TLSv1.2 hello'''
    pass


class SNIDifferentTypeRev12PFS(SNIDifferentTypeRev, NormalHandshake12PFS):
    '''As with SNIDifferentTypeRev but in PFS TLSv1.2 hello'''
    pass


class SNIOverflow(NormalHandshake):
    '''Send server name indication with data length exceeding stated size'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(name)
        # first four bytes are the header, last one we truncate to exceed size
        ext_data = sni_extension.bytes[4:-1]
        sni_extension = Extension.create(extension_type=Extension.ServerName,
                                         data=ext_data)

        record = self.make_hello([sni_extension])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_sni_hello(self.ipaddress))


class SNIOverflow12(SNIOverflow, NormalHandshake12):
    '''as with SNIOverflow but in TLSv1.2 hello'''
    pass


class SNIOverflow12PFS(SNIOverflow, NormalHandshake12PFS):
    '''as with SNIOverflow but in TLSv1.2 hello'''
    pass


class SNIUnderflow(SNIOverflow):
    '''Send server name indication with data length smaller than size inside'''

    def make_sni_hello(self, name):
        sni_extension = ServerNameExtension.create(name)
        # first four bytes are the header
        ext_data = sni_extension.bytes[4:] + b'\x00\x00\x00'
        sni_extension = Extension.create(extension_type=Extension.ServerName,
                                         data=ext_data)

        record = self.make_hello([sni_extension])

        return record


class SNIUnderflow12(SNIUnderflow, NormalHandshake12):
    '''As with SNIUnderflow, but in TLSv1.2 hello'''
    pass


class SNIUnderflow12PFS(SNIUnderflow, NormalHandshake12PFS):
    '''As with SNIUnderflow, but in PFS TLSv1.2 hello'''
    pass


class SecureRenegoOverflow(NormalHandshake):
    '''Send secure renegotiation with data length exceeding stated size'''

    def make_secure_renego_ext(self, payload):
        secure_renego = Extension.create(
            extension_type=Extension.RenegotiationInfo,
            data=payload)
        return self.make_hello([secure_renego])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte of secure renegotiation extension specifies the
        # length of the array of bytes in it, but don't provide the
        # required amount
        sock.send(self.make_secure_renego_ext(b'\x0c0123456789'))


class SecureRenegoOverflow12(SecureRenegoOverflow, NormalHandshake12):
    '''As with SecureRenegotOverflow, inside TLSv1.2 hello'''
    pass


class SecureRenegoOverflow12PFS(SecureRenegoOverflow, NormalHandshake12PFS):
    '''As with SecureRenegoOverflow, inside TLSv1.2 PFS hello'''
    pass


class SecureRenegoUnderflow(SecureRenegoOverflow):
    '''Send secure renegotiation with data length lower than stated size'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # again, first byte specifies zero-length array, rest of bytes
        # are just padding to make the extension large
        sock.send(self.make_secure_renego_ext(b'\x00\x00\x00\x00\x00'))


class SecureRenegoUnderflow12(SecureRenegoUnderflow, NormalHandshake12):
    '''As with SecureRenegoUnderflow, inside TLSv1.2 hello'''
    pass


class SecureRenegoUnderflow12PFS(SecureRenegoUnderflow, NormalHandshake12PFS):
    '''As with SecureRenegoUnderflow, inside PFS TLSv1.2 hello'''
    pass


class SecureRenegoNonEmpty(SecureRenegoOverflow):
    '''Send secure renegotiation with renegotiation payload'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # send a correctly formatted extension, but with a non-empty
        # payload (indicating renegotiated connection)
        sock.send(self.make_secure_renego_ext(b'\x0c012345678901'))


class SecureRenegoNonEmpty12(SecureRenegoNonEmpty, NormalHandshake12):
    '''Send secure renegotiation with renegotiation payload in TLSv1.2 hello'''
    pass


class SecureRenegoNonEmpty12PFS(SecureRenegoNonEmpty, NormalHandshake12PFS):
    '''As with SecureRenegoNonEmpty12, but with PFS ciphers'''
    pass


class SecureRenegoNull(SecureRenegoOverflow):
    '''Send secure renegotiation extension that is completely empty'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # While the proper formatting is to send an empty array, and not
        # no array, some servers still accept it
        sock.send(self.make_secure_renego_ext(b''))


class SecureRenegoNull12(SecureRenegoNull, NormalHandshake12):
    '''As with SecureRenegoNull, but in TLSv1.2 hello'''
    pass


class SecureRenegoNull12PFS(SecureRenegoNull, NormalHandshake12PFS):
    '''As with SecureRenegoNull, but in PFS TLSv1.2 hello'''
    pass


class MaxFragmentNull(NormalHandshake):
    '''Send maximum fragment length extension that is completely empty'''

    def make_fragment_hello(self, payload):
        max_fragment = Extension.create(
            extension_type=Extension.MaxFragmentLength,
            data=payload)

        record = self.make_hello([max_fragment])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension needs a single byte value, don't provide it
        sock.send(self.make_fragment_hello(b''))


class MaxFragmentNull12(MaxFragmentNull, NormalHandshake12):
    '''As with MaxFragmentNull, but in TLSv1.2 hello'''
    pass


class MaxFragmentNull12PFS(MaxFragmentNull, NormalHandshake12PFS):
    '''As with MaxFragmentNull, but in PFS TLSv1.2 hello'''
    pass


class MaxFragmentInvalid(MaxFragmentNull):
    '''Send maximum fragment length extension with invalid value'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid values are between 1 and 4 inclusive
        sock.send(self.make_fragment_hello(b'\x08'))


class MaxFragmentInvalid12(MaxFragmentInvalid, NormalHandshake12):
    '''As with MaxFragmentInvalid, but in TLSv1.2 hello'''
    pass


class MaxFragmentInvalid12PFS(MaxFragmentInvalid, NormalHandshake12PFS):
    '''As with MaxFragmentInvalid, but in PFS TLSv1.2 hello'''
    pass


class ClientCertURLsNotNull(NormalHandshake):
    '''Send client certificate URL indication extension that is not empty'''

    def make_cert_urls_hello(self, payload):
        client_cert_url_ext = Extension.create(
            extension_type=Extension.ClientCertificateUrl,
            data=payload)

        record = self.make_hello([client_cert_url_ext])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # correctly formatted does not include any data
        sock.send(self.make_cert_urls_hello(b'\x08\x00'))


class ClientCertURLsNotNull12(ClientCertURLsNotNull, NormalHandshake12):
    '''As with ClientCertURLsNotNull, but in TLSv1.2 hello'''
    pass


class ClientCertURLsNotNull12PFS(ClientCertURLsNotNull, NormalHandshake12PFS):
    '''As with ClientCertURLsNotNull, but in PFS TLSv1.2 hello'''
    pass


class TrustedCANull(NormalHandshake):
    '''Send trusted CA keys extension with completely empty payload'''

    def make_trusted_ca_hello(self, payload):
        trusted_ca_ext = Extension.create(
            extension_type=Extension.TrustedCAKeys,
            data=payload)

        record = self.make_hello([trusted_ca_ext])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal formatting is a complex structure
        sock.send(self.make_trusted_ca_hello(b''))


class TrustedCANull12(TrustedCANull, NormalHandshake12):
    '''As with TrustedCANull but in TLSv1.2 hello'''
    pass


class TrustedCANull12PFS(TrustedCANull, NormalHandshake12PFS):
    '''As with TrustedCANull, but in PFS TLSv1.2 hello'''
    pass


class TrustedCAOverflow(TrustedCANull):
    '''Send trusted CA keys extension smaller than length inside indicates'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # in a normal structure, the first two bytes are the overall length
        # of list with extension data
        # a typical payload includes type (1B) and sha1 hash (20B)
        sock.send(self.make_trusted_ca_hello(b'\x00\x15'))


class TrustedCAOverflow12(TrustedCAOverflow, NormalHandshake12):
    '''As with TrustedCAOverflow but in TLSv1.2 hello'''
    pass


class TrustedCAOverflow12PFS(TrustedCAOverflow, NormalHandshake12PFS):
    '''As with TrustedCAOverflow but in PFS TLSv1.2 hello'''
    pass


class TrustedCAUnderflow(TrustedCANull):
    '''Send trusted CA keys extension larger than length inside indicates'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')

        # type key_sha1_hash + sha1 hash (20 bytes)
        authority = b'\x01' + b'a'*20
        # payload has a 2 byte length and then an array of items,
        # add null byte at end to cause the underflow
        ext_data = struct.pack('!H', len(authority)) + authority + b'\x00'

        sock.send(self.make_trusted_ca_hello(ext_data))


class TrustedCAUnderflow12(TrustedCAUnderflow, NormalHandshake12):
    '''As with TrustedCAUnderflow but in TLSv1.2 hello'''
    pass


class TrustedCAUnderflow12PFS(TrustedCAUnderflow, NormalHandshake12PFS):
    '''As with TrustedCAUnderflow but in PFS TLSv1.2 hello'''
    pass


class TruncatedHMACNotNull(NormalHandshake):
    '''Send a truncated HMAC extension with a non empty payload'''

    def make_truncated_hmac_hello(self, payload):
        truncated_hmac = Extension.create(
            extension_type=Extension.TruncateHMAC,
            data=payload)

        record = self.make_hello([truncated_hmac])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # properly formatted extension has no data at all
        sock.send(self.make_truncated_hmac_hello(b'\x0c'))


class TruncatedHMACNotNull12(TruncatedHMACNotNull, NormalHandshake12):
    '''As with TruncatedHMACNotNull but in TLSv1.2 hello'''
    pass


class TruncatedHMACNotNull12PFS(TruncatedHMACNotNull, NormalHandshake12PFS):
    '''As with TruncatedHMACNotNull but in PFS TLSv1.2 hello'''
    pass


class OCSPNull(NormalHandshake):
    '''Send status request extension with empty payload'''

    def make_ocsp_hello(self, payload):
        status_request = Extension.create(
            extension_type=Extension.StatusRequest,
            data=payload)

        record = self.make_hello([status_request])

        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normally the status request is a complex structure, don't include
        # it
        sock.send(self.make_ocsp_hello(b''))


class OCSPNull12(OCSPNull, NormalHandshake12):
    '''As with OCSPNull but in TLSv1.2 hello'''
    pass


class OCSPNull12PFS(OCSPNull, NormalHandshake12PFS):
    '''As with OCSPNull but in PFS TLSv1.2 hello'''
    pass


class OCSPOverflow(OCSPNull):
    '''Send status request ext smaller than the length inside indicates'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the request has three fields - type (one byte) and two arrays
        # with 2 byte long headers, truncate the second length header
        sock.send(self.make_ocsp_hello(b'\x01\x00\x00\x00'))


class OCSPOverflow12(OCSPOverflow, NormalHandshake12):
    '''As with OCSPOverflow but in TLSv1.2 hello'''
    pass


class OCSPOverflow12PFS(OCSPOverflow, NormalHandshake12PFS):
    '''As with OCSPOverflow but in PFS TLSv1.2 hello'''
    pass


class OCSPUnderflow(OCSPNull):
    '''Send status request ext larger than the length inside indicate'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # correctly formed request, two extra zero bytes
        sock.send(self.make_ocsp_hello(b'\x01' + b'\x00' * 6))


class OCSPUnderflow12(OCSPUnderflow, NormalHandshake12):
    '''As with OCSPUnderflow but in TLSv1.2 hello'''
    pass


class OCSPUnderflow12PFS(OCSPUnderflow, NormalHandshake12PFS):
    '''As with OCSPUnderflow but in PFS TLSv1.2 hello'''
    pass


class DoubleExtension(NormalHandshake):
    '''Duplicate secure renegotiation extension'''

    def make_double_ext_hello(self):
        secure_renego = Extension.create(
            extension_type=Extension.RenegotiationInfo,
            data=b'\x00')

        record = self.make_hello([secure_renego,
                                  secure_renego])
        return record

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # correct Client Hello messages must not contain two extensions
        # of the same type
        sock.send(self.make_double_ext_hello())


class DoubleExtension12(DoubleExtension, NormalHandshake12):
    '''Duplicate secure renegotiation extension in TLSv1.2 hello'''
    pass


class DoubleExtension12PFS(DoubleExtension, NormalHandshake12PFS):
    '''Duplicate secure renegotiation extension in PFS TLSv1.2 hello'''
    pass


class UserMappingNull(NormalHandshake):
    '''Send empty user mapping extension in hello'''

    def make_user_mapping_ext(self, value):
        user_mapping_ext = Extension.create(
            extension_type=6,
            data=value)
        return self.make_hello([user_mapping_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # extension consists of an array and the array needs at least one
        # element, don't send any
        sock.send(self.make_user_mapping_ext(b''))


class UserMappingNull12(UserMappingNull, NormalHandshake12):
    '''Send empty user mapping extension in TLSv1.2 hello'''
    pass


class UserMappingNull12PFS(UserMappingNull, NormalHandshake12PFS):
    '''Send empty user mapping extension in PFS TLSv1.2 hello'''
    pass


class UserMappingOverflow(UserMappingNull):
    '''Send user mapping extension with length longer than present in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # extension consists of an array and the array needs at least one
        # element, send the length of array (one byte) longer than payload size
        sock.send(self.make_user_mapping_ext(b'\x02\x40'))


class UserMappingOverflow12(UserMappingOverflow, NormalHandshake12):
    '''As with UserMappingOverflow but in TLSv1.2 hello'''
    pass


class UserMappingOverflow12PFS(UserMappingOverflow, NormalHandshake12PFS):
    '''As with UserMappingOverflow but in PFS TLSv1.2 hello'''
    pass


class ClientAuthzNull(NormalHandshake):
    '''Send empty client authz extension in hello'''

    def make_client_authz_hello(self, value):
        client_authz_ext = Extension.create(
            extension_type=7,
            data=value)
        return self.make_hello([client_authz_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_client_authz_hello(b''))


class ClientAuthzNull12(ClientAuthzNull, NormalHandshake12):
    '''Send empty client authz extension in TLSv1.2 hello'''
    pass


class ClientAuthzNull12PFS(ClientAuthzNull, NormalHandshake12PFS):
    '''Send empty client authz extension in PFS TLSv1.2 hello'''
    pass


class ClientAuthzOverflow(ClientAuthzNull):
    '''Send client authz extension with length longer than data in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has one byte length as first element then
        # the array, make the array length longer than real payload
        sock.send(self.make_client_authz_hello(b'\x04\x00\x01'))


class ClientAuthzOverflow12(ClientAuthzOverflow, NormalHandshake12):
    '''As with ClientAuthzOverflow but in TLSv1.2 hello'''
    pass


class ClientAuthzOverflow12PFS(ClientAuthzOverflow, NormalHandshake12PFS):
    '''As with ClientAuthzOverflow but in PFS TLSv1.3 hello'''
    pass


class ServerAuthzNull(ClientAuthzNull):
    '''Send empty server authz extension in hello'''

    def make_client_authz_hello(self, value):
        server_authz_ext = Extension.create(
            extension_type=8,
            data=value)
        return self.make_hello([server_authz_ext])


class ServerAuthzNull12(ServerAuthzNull, NormalHandshake12):
    '''Send empty server authz extension in TLSv1.2 hello'''
    pass


class ServerAuthzNull12PFS(ServerAuthzNull, NormalHandshake12PFS):
    '''Send empty server authz extension in PFS TLSv1.2 hello'''
    pass


class ServerAuthzOverflow(ServerAuthzNull, ClientAuthzOverflow):
    '''Send server authz extension with length longer than data in hello'''
    pass


class ServerAuthzOverflow12(ServerAuthzOverflow, NormalHandshake12):
    '''As with ServerAuthzOverflow but in TLSv1.2 hello'''
    pass


class ServerAuthzOverflow12PFS(ServerAuthzOverflow, NormalHandshake12PFS):
    '''As with ServerAuthzOverflow but in PFS TLSv1.2 hello'''
    pass


class CertTypeNull(NormalHandshake):
    '''Send empty cert type extension in hello'''

    def make_cert_type_hello(self, value):
        cert_type_ext = Extension.create(
            extension_type=9,
            data=value)
        return self.make_hello([cert_type_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_cert_type_hello(b''))


class CertTypeNull12(CertTypeNull, NormalHandshake12):
    '''Send empty cert type extension in TLSv1.2 hello'''
    pass


class CertTypeNull12PFS(CertTypeNull, NormalHandshake12PFS):
    '''Send empty cert type extension in PFS TLSv1.2 hello'''
    pass


class CertTypeOverflow(CertTypeNull):
    '''Send cert type extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte is a length of array, send invalid one
        sock.send(self.make_cert_type_hello(b'\x04\x01'))


class CertTypeOverflow12(CertTypeOverflow, NormalHandshake12):
    '''Send cert type extension with too large length in TLSv1.2 hello'''
    pass


class CertTypeOverflow12PFS(CertTypeOverflow, NormalHandshake12PFS):
    '''Send cert type extension with too large length in PFS TLSv1.2 hello'''
    pass


class SupportedGroupsNull(NormalHandshake):
    '''Send empty supported groups extension in hello'''

    def make_supported_groups_hello(self, value):
        supported_groups_ext = Extension.create(
            extension_type=10,
            data=value)
        return self.make_hello([supported_groups_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_supported_groups_hello(b''))


class SupportedGroupsNull12(SupportedGroupsNull, NormalHandshake12):
    '''Send empty supported groups extension in TLSv1.2 hello'''
    pass


class SupportedGroupsNull12PFS(SupportedGroupsNull, NormalHandshake12PFS):
    '''Send empty supported groups extension in PFS TLSv1.2 hello'''
    pass


class SupportedGroupsOddLen(SupportedGroupsNull):
    '''Send supported groups extension with invalid length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has a two byte length and two byte elements,
        # truncate the second element
        sock.send(self.make_supported_groups_hello(b'\x00\x03\x00\x17\x00'))


class SupportedGroupsOddLen12(SupportedGroupsOddLen, NormalHandshake12):
    '''Send supported groups extension with invalid length in TLSv1.2 hello'''
    pass


class SupportedGroupsOddLen12PFS(SupportedGroupsOddLen, NormalHandshake12PFS):
    '''As with SupportedGroupsOddLen but in PFS TLSv1.2 hello'''
    pass


class SupportedGroupsOverflow(SupportedGroupsNull):
    '''Send supported groups extension with length larger than data'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has a two byte length and two byte elements,
        # truncate the whole second element
        sock.send(self.make_supported_groups_hello(b'\x00\x04\x00\x17'))


class SupportedGroupsOverflow12(SupportedGroupsOverflow, NormalHandshake12):
    '''As with SupportedGroupsOverflow but in TLSv1.2 hello'''
    pass


class SupportedGroupsOverflow12PFS(SupportedGroupsOverflow,
        NormalHandshake12PFS):
    '''As with SupportedGroupsOverflow but in PFS TLSv1.2 hello'''
    pass


class ECPointFormatsNull(NormalHandshake):
    '''Send empty ec point formats extension in hello'''

    def make_point_formats_hello(self, value):
        point_formats_ext = Extension.create(
            extension_type=11,
            data=value)
        return self.make_hello([point_formats_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_point_formats_hello(b''))


class ECPointFormatsNull12(ECPointFormatsNull, NormalHandshake12):
    '''Send empty ec point formats extension in TLSv1.2 hello'''
    pass


class ECPointFormatsNull12PFS(ECPointFormatsNull, NormalHandshake12PFS):
    '''Send empty ec point formats extension in PFS TLSv1.2 hello'''
    pass


class ECPointFormatsOverflow(ECPointFormatsNull):
    '''Send ec point formats extension with length larger than data in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte is the length of array, send too large one
        sock.send(self.make_point_formats_hello(b'\x04\x00'))


class ECPointFormatsOverflow12(ECPointFormatsOverflow, NormalHandshake12):
    '''As with ECPointFormatsOverflow but in TLSv1.2 hello'''
    pass


class ECPointFormatsOverflow12PFS(ECPointFormatsOverflow,
                                   NormalHandshake12PFS):
    '''As with ECPointFormatsOverflow but in PFS TLSv1.2 hello'''
    pass


class ECPointFormatsCompOnly(ECPointFormatsNull):
    '''Send ec point formats extension without uncompressed format'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the uncompressed format is mandatory, send extension without it
        sock.send(self.make_point_formats_hello(b'\x02\x01\x02'))


class ECPointFormatsCompOnly12(ECPointFormatsCompOnly, NormalHandshake12):
    '''As with ECPointFormatsCompOnly but in TLSv1.2 hello'''
    pass


class ECPointFormatsCompOnly12PFS(ECPointFormatsCompOnly,
                                   NormalHandshake12PFS):
    '''As with ECPointFormatsCompOnly but in PFS TLS v1.2 hello'''
    pass


class SRPNull(NormalHandshake):
    '''Send empty srp extension in hello'''

    def make_srp_hello(self, value):
        srp_ext = Extension.create(
            extension_type=12,
            data=value)
        return self.make_hello([srp_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normally the extension has client's identity, don't include any
        sock.send(self.make_srp_hello(b''))


class SRPNull12(SRPNull, NormalHandshake12):
    '''Send empty srp extension in TLSv1.2 hello'''
    pass


class SRPNull12PFS(SRPNull, NormalHandshake12PFS):
    '''Send empty srp extension in PFS TLSv1.2 hello'''
    pass


class SRPOverflow(SRPNull):
    '''Send srp extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first byte is the length, send too large
        sock.send(self.make_srp_hello(b'\x06test'))


class SRPOverflow12(SRPOverflow, NormalHandshake12):
    '''Send srp extension with too large length in TLSv1.2 hello'''
    pass


class SRPOverflow12PFS(SRPOverflow, NormalHandshake12PFS):
    '''Send srp extension with too large length in PFS TLSv1.2 hello'''
    pass


class SigAlgsNull(NormalHandshake):
    '''Send empty signature algorithms extension in hello'''

    def make_signature_alg_hello(self, value):
        sig_algs_ext = Extension.create(
            extension_type=13,
            data=value)
        return self.make_hello([sig_algs_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_signature_alg_hello(b''))


class SigAlgsNull12(SigAlgsNull, NormalHandshake12):
    '''Send empty signature algorithms extension in TLSv1.2 hello'''
    pass


class SigAlgsNull12PFS(SigAlgsNull, NormalHandshake12PFS):
    '''Send empty signature algorithms extension in PFS TLSv1.2 hello'''
    pass


class SigAlgsOddLen(SigAlgsNull):
    '''Send signature algorithms extensions with invalid length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has two byte long elements, truncate the last one
        sock.send(self.make_signature_alg_hello(b'\x00\x05'
                                                 b'\x04\x01'
                                                 b'\x04\x03\x04'))

class SigAlgsOddLen12(SigAlgsOddLen, NormalHandshake12):
    '''As in SigAlgsOddLen but in TLSv1.2 hello'''
    pass


class SigAlgsOddLen12PFS(SigAlgsOddLen, NormalHandshake12PFS):
    '''As in SigAlgsOddLen but in PFS TLSv1.2 hello'''
    pass


class SigAlgsOverflow(SigAlgsNull):
    '''Send signature algorithms extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the first two bytes are the length of the array, send too large one
        sock.send(self.make_signature_alg_hello(b'\x00\x06'
                                                 b'\x04\x01'
                                                 b'\x04\x03'))


class SigAlgsOverflow12(SigAlgsOverflow, NormalHandshake12):
    '''As in SigAlgsOverflow but in TLSv1.2 hello'''
    pass


class SigAlgsOverflow12PFS(SigAlgsOverflow, NormalHandshake12PFS):
    '''As in SigAlgsOverflow but in PFS TLSv1.2 hello'''
    pass


class UseSrtpNull(NormalHandshake):
    '''Send empty use srtp extension in hello'''

    def make_use_srtp_hello(self, value):
        use_srtp_ext = Extension.create(
            extension_type=14,
            data=value)
        return self.make_hello([use_srtp_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has an array, don't send anything
        sock.send(self.make_use_srtp_hello(b''))


class UseSrtpNull12(UseSrtpNull, NormalHandshake12):
    '''Send empty use srtp extension in TLSv1.2 hello'''
    pass

class UseSrtpNull12PFS(UseSrtpNull, NormalHandshake12PFS):
    '''Send empty use srtp extension in PFS TLSv1.2 hello'''
    pass

class UseSrtpOddLen(UseSrtpNull):
    '''Send use srtp extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension starts with a two byte length of two-byte elements
        # and the second array is optional with a simple binary string
        sock.send(self.make_use_srtp_hello(b'\x00\x05'
                                            b'\x00\x01\x00\x05\x00'
                                            b'\x00'))

class UseSrtpOddLen12(UseSrtpOddLen, NormalHandshake12):
    '''Send use srtp extension with too large length in TLSv1.2 hello'''
    pass


class UseSrtpOddLen12PFS(UseSrtpOddLen, NormalHandshake12PFS):
    '''Send use srtp extension with too large length in PFS TLSv1.2 hello'''
    pass


class UseSrtpOverflow(UseSrtpNull):
    '''Send use srtp extension with length larger than payload'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension has two arrays, one has a two byte length the other
        # a one byte length, make the first array longer than payload
        sock.send(self.make_use_srtp_hello(b'\x00\x06'
                                            b'\x00\x01\x00\x05'))


class UseSrtpOverflow12(UseSrtpOverflow, NormalHandshake12):
    '''Send use srtp extension with length larger than payload in TLSv1.2'''
    pass


class UseSrtpOverflow12PFS(UseSrtpOverflow, NormalHandshake12PFS):
    '''As in UseSrtpOverflow but in PFS TLSv1.2 hello'''
    pass


class HeartbeatNull(NormalHandshake):
    '''Send empty heartbeat extension in hello'''

    def make_heartbeat_hello(self, value):
        heartbeat_ext = Extension.create(
            extension_type=15,
            data=value)
        return self.make_hello([heartbeat_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension is a single byte value, don't include it
        sock.send(self.make_heartbeat_hello(b''))


class HeartbeatNull12(HeartbeatNull, NormalHandshake12):
    '''Send empty heartbeat extension in TLSv1.2 hello'''
    pass


class HeartbeatNull12PFS(HeartbeatNull, NormalHandshake12PFS):
    '''Send empty heartbeat extension in PFS TLSv1.2 hello'''
    pass


class HeartbeatInvalid(HeartbeatNull):
    '''Send heartbeat extension with invalid value in hello'''

    def test(self, sock):
        # the valid values are 1 and 2, send something else
        sock.send(self.make_heartbeat_hello(b'\x00'))


class HeartbeatInvalid12(HeartbeatInvalid, NormalHandshake12):
    '''Send heartbeat extension with invalid value in TLSv1.2 hello'''
    pass


class HeartbeatInvalid12PFS(HeartbeatInvalid, NormalHandshake12PFS):
    '''Send heartbeat extension with invalid value in PFS TLSv1.2 hello'''
    pass


class ALPNNull(NormalHandshake):
    '''Send empty ALPN extension in hello'''

    def make_alpn_hello(self, value):
        alpn_ext = Extension.create(
            extension_type=16,
            data=value)
        return self.make_hello([alpn_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension has an array, don't send anything
        sock.send(self.make_alpn_hello(b''))


class ALPNNull12(ALPNNull, NormalHandshake12):
    '''Send empty APLN extension in TLSv1.2 hello'''
    pass


class ALPNNull12PFS(ALPNNull, NormalHandshake12PFS):
    '''Send empty ALPN extension in PFS TLSv1.2 hello'''
    pass


class ALPNUnknown(ALPNNull):
    '''Send ALPN extension with only unknown protocol in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension is an array of arrays, the external array has
        # two byte length header, the internal arrays have one byte length
        sock.send(self.make_alpn_hello(b'\x00\x08'
                                        b'\x07unknown'))


class ALPNUnknown12(ALPNUnknown, NormalHandshake12):
    '''Send ALPN extension with only unknown protocol in TLSv1.2 hello'''
    pass


class ALPNUnknown12PFS(ALPNUnknown, NormalHandshake12PFS):
    '''Send ALPN extension with only unknown protocol in PFS TLSv1.2 hello'''
    pass


class ALPNOverflow(ALPNNull):
    '''Send ALPN extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # the extension is an array of arrays, the external array has
        # two byte length header, the internal arrays have one byte length
        # make the external length too large
        sock.send(self.make_alpn_hello(b'\x00\x10'
                                        b'\x08http/1.1'))


class ALPNOverflow12(ALPNOverflow, NormalHandshake12):
    '''Send ALPN extension with too large length in TLSv1.2 hello'''
    pass


class ALPNOverflow12PFS(ALPNOverflow, NormalHandshake12PFS):
    '''Send ALPN extension with too large length in PFS TLSv1.2 hello'''
    pass


class OCSPv2Null(NormalHandshake):
    '''Send empty OCSPv2 staple extension in hello'''

    def make_ocspv2_hello(self, value):
        ocspv2_ext = Extension.create(
            extension_type=17,
            data=value)
        return self.make_hello([ocspv2_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal encoding has a list of complex items, don't include anything
        sock.send(self.make_ocspv2_hello(b''))


class OCSPv2Null12(OCSPv2Null, NormalHandshake12):
    '''Send empty OCSPv2 staple extension in TLSv1.2 hello'''
    pass


class OCSPv2Null12PFS(OCSPv2Null, NormalHandshake12PFS):
    '''Send empty OCSPv2 staple extension in PFS TLSv1.2 hello'''
    pass


class OCSPv2Overflow(OCSPv2Null):
    '''Send OCSPv2 staple extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        data = (b'\x00\x10'  # overall length of extension (too large)
                b'\x01'  # first request type (ocsp)
                b'\x00\x04'  # request length
                b'\x00\x00'  # responder ID list length
                b'\x00\x00'  # request extensions list length
                b'\x02'  # second request type (ocsp_multi)
                b'\x00\x04'  # request length
                b'\x00\x00'  # responder ID list length
                b'\x00\x00')  # request extensions list length
        sock.send(self.make_ocspv2_hello(data))


class OCSPv2Overflow12(OCSPv2Overflow, NormalHandshake12):
    '''Send OCSPv2 staple extension with too large length in TLSv1.2 hello'''
    pass


class OCSPv2Overflow12PFS(OCSPv2Overflow, NormalHandshake12PFS):
    '''As with OCSPv2Overflow but in PFS TLSv1.2 hello'''
    pass


class SignedCertTSNotNull(NormalHandshake):
    '''Send hello with signed certificate timestamp that is not empty'''

    def make_signed_cert_ts_hello(self, value):
        signed_cert_ts_ext = Extension.create(
            extension_type=18,
            data=value)
        return self.make_hello([signed_cert_ts_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension should be empty
        sock.send(self.make_signed_cert_ts_hello(b'\x04'))

class SignedCertTSNotNull12(SignedCertTSNotNull, NormalHandshake12):
    '''As with SignedCertTSNotNull but in TLSv1.2 hello'''
    pass


class SignedCertTSNotNull12PFS(SignedCertTSNotNull, NormalHandshake12PFS):
    '''As with SignedCertTSNotNull but in PFS TLSv1.2 hello'''
    pass


class ClientCertTypeNull(NormalHandshake):
    '''Send empty client certificate type extension in hello'''

    def make_client_cert_type_hello(self, value):
        client_cert_type_ext = Extension.create(
            extension_type=19,
            data=value)
        return self.make_hello([client_cert_type_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension has an array
        sock.send(self.make_client_cert_type_hello(b''))


class ClientCertTypeNull12(ClientCertTypeNull, NormalHandshake12):
    '''Send empty client certificate type extension in TLSv1.2 hello'''
    pass


class ClientCertTypeNull12PFS(ClientCertTypeNull, NormalHandshake12PFS):
    '''Send empty client certificate type extension in PFS TLSv1.2 hello'''
    pass


class ClientCertTypeOverflow(ClientCertTypeNull):
    '''Send client certificate type extension with too large length in hello'''

    def test(self, sock):
        logging.debug('sending Client Hello...')
        # first byte is the length of the array, send too large
        sock.send(self.make_client_cert_type_hello(b'\x04\x02\x01\x00'))


class ClientCertTypeOverflow12(ClientCertTypeOverflow, NormalHandshake12):
    '''As with ClientCertTypeOverflow, but in TLSv1.2 hello'''
    pass


class ClientCertTypeOverflow12PFS(ClientCertTypeOverflow,
                                  NormalHandshake12PFS):
    '''As with ClientCertTypeOverflow but in PFS TLSv1.2 hello'''
    pass


class ServerCertTypeNull(NormalHandshake):
    '''Send empty server certificate type extension in hello'''

    def make_server_cert_type_hello(self, value):
        server_cert_type_ext = Extension.create(
            extension_type=20,
            data=value)
        return self.make_hello([server_cert_type_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # valid extension has an array
        sock.send(self.make_server_cert_type_hello(b''))


class ServerCertTypeNull12(ServerCertTypeNull, NormalHandshake12):
    '''Send empty server certificate type extension in TLSv1.2 hello'''
    pass


class ServerCertTypeNull12PFS(ServerCertTypeNull, NormalHandshake12PFS):
    '''Send empty server certificate type extension in PFS TLSv1.2 hello'''
    pass


class ServerCertTypeOverflow(ServerCertTypeNull):
    '''Send server certificate type extension with too large length in hello'''

    def test(self, sock):
        logging.debug('sending Client Hello...')
        # first byte is the length of the array, send too large
        sock.send(self.make_server_cert_type_hello(b'\x04\x02\x01\x00'))


class ServerCertTypeOverflow12(ServerCertTypeOverflow, NormalHandshake12):
    '''As with ServerCertTypeOverflow, but in TLSv1.2 hello'''
    pass


class ServerCertTypeOverflow12PFS(ServerCertTypeOverflow,
                                  NormalHandshake12PFS):
    '''As with ServerCertTypeOverflow but in PFS TLSv1.2 hello'''
    pass


class PaddingNull(NormalHandshake):
    '''Send empty padding extension in hello'''

    def make_padding_hello(self, value):
        padding_ext = Extension.create(
            extension_type=21,
            data=value)
        return self.make_hello([padding_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # there is no invalid encoding of extension, send an empty one
        sock.send(self.make_padding_hello(b''))


class PaddingNull12(PaddingNull, NormalHandshake12):
    '''Send empty padding extension in TLSv1.2 hello'''
    pass


class PaddingNull12PFS(PaddingNull, NormalHandshake12PFS):
    '''Send empty padding extension in PFS TLSv1.2 hello'''
    pass


class Padding300Byte(PaddingNull):
    '''Use padding extension to send 300 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (300 - (64 - 5) - 4)))


class Padding300Byte12(PaddingNull, NormalHandshake12):
    '''Use padding extension to send 300 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (300 - (88 - 5) - 4)))


class Padding300Byte12PFS(PaddingNull, NormalHandshake12PFS):
    '''Use padding extension to send 300 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (300 - (144 - 5) - 4)))


class Padding600Byte(PaddingNull):
    '''Use padding extension to send 600 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (600 - (64 - 5) - 4)))


class Padding600Byte12(PaddingNull, NormalHandshake12):
    '''Use padding extension to send 600 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (600 - (88 - 5) - 4)))


class Padding600Byte12PFS(PaddingNull, NormalHandshake12PFS):
    '''Use padding extension to send 600 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (600 - (144 - 5) - 4)))


class Padding16384Byte(PaddingNull):
    '''Use padding extension to send 16384 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        # 16384 is the largest size that can be sent in a single record layer
        sock.send(self.make_padding_hello(b'\x00' * (16384 - (64 - 5) - 4)))


class Padding16384Byte12(PaddingNull, NormalHandshake12):
    '''Use padding extension to send 16384 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16384 - (88 - 5) - 4)))


class Padding16384Byte12PFS(PaddingNull, NormalHandshake12PFS):
    '''Use padding extension to send 16384 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16384 - (144 - 5) - 4)))


class Padding16385Byte(Probe):
    '''Use padding extension to send 16385 byte large hello'''

    def __init__(self):
        super(Padding16385Byte, self).__init__()
        self.hello_version = TLSRecord.TLS1_0
        self.ciphers = DEFAULT_CIPHERS

    def make_padding_hello(self, value):
        padding_ext = Extension.create(
            extension_type=21,
            data=value)
        RECORD_MAX=16384
        hello = ClientHelloMessage.create(self.hello_version,
                                          b'01234567890123456789012345678901',
                                          self.ciphers,
                                          extensions=[padding_ext])
        hello_bytes = hello.bytes
        records = [TLSRecord.create(content_type=TLSRecord.Handshake,
                                    version=TLSRecord.TLS1_0,
                                    message=hello_bytes[i:i+RECORD_MAX]).bytes
                   for i in range(0, len(hello_bytes), RECORD_MAX)]
        return b''.join(records)

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # hello is 64 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16385 - (64 - 5) - 4)))


class Padding16385Byte12(Padding16385Byte):
    '''Use padding extension to send 16385 byte large TLSv1.2 hello'''

    def __init__(self):
        super(Padding16385Byte, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_12_CIPHERS

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # TLSv1.2 hello is 88 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16385 - (88 - 5) - 4)))


class Padding16385Byte12PFS(Padding16385Byte):
    '''Use padding extension to send 16385 byte large PFS TLSv1.2 hello'''

    def __init__(self):
        super(Padding16385Byte, self).__init__()
        self.hello_version = TLSRecord.TLS1_2
        self.ciphers = DEFAULT_PFS_CIPHERS

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are
        # record layer overhead, extensions length is already included
        # but extension id and extension length is not, totalling 4 bytes
        sock.send(self.make_padding_hello(b'\x00' * (16385 - (144 - 5) - 4)))


class Padding16387Byte(Padding16385Byte):
    '''Use padding extension to send 16387 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16387 - (64 - 5) - 4)))


class Padding16387Byte12(Padding16385Byte12):
    '''Use padding extension to send 16387 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16387 - (88 - 5) - 4)))


class Padding16387Byte12PFS(Padding16385Byte12PFS):
    '''Use padding extension to send 16387 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16387 - (144 - 5) - 4)))


class Padding16389Byte(Padding16385Byte):
    '''Use padding extension to send 16389 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16389 - (64 - 5) - 4)))


class Padding16389Byte12(Padding16385Byte12):
    '''Use padding extension to send 16389 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16389 - (88 - 5) - 4)))


class Padding16389Byte12PFS(Padding16385Byte12PFS):
    '''Use padding extension to send 16389 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (16389 - (144 - 5) - 4)))


class Padding17520Byte(Padding16385Byte):
    '''Use padding extension to send 17520 byte large hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (17520 - (64 - 5) - 4)))


class Padding17520Byte12(Padding16385Byte12):
    '''Use padding extension to send 17520 byte large TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (17520 - (88 - 5) - 4)))


class Padding17520Byte12PFS(Padding16385Byte12PFS):
    '''Use padding extension to send 17520 byte large PFS TLSv1.2 hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        sock.send(self.make_padding_hello(b'\x00' * (17520 - (144 - 5) - 4)))


class EtMNotNull(NormalHandshake):
    '''Send not empty encrypt then mac extension in hello'''

    def make_etm_hello(self, value):
        etm_ext = Extension.create(
            extension_type=22,
            data=value)
        return self.make_hello([etm_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must be empty
        sock.send(self.make_etm_hello(b'\x04'))


class EtMNotNull12(EtMNotNull, NormalHandshake12):
    '''Send not empty encrypt then mac extension in TLSv1.2 hello'''
    pass


class EtMNotNull12PFS(EtMNotNull, NormalHandshake12PFS):
    '''Send not empty encrypt then mac extension in PFS TLSv1.2 hello'''
    pass


class EMSNotNull(NormalHandshake):
    '''Send not empty extended master secret extension in hello'''

    def make_ems_hello(self, value):
        ems_ext = Extension.create(
            extension_type=23,
            data=value)
        return self.make_hello([ems_ext])


    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must be empty
        sock.send(self.make_ems_hello(b'\x04'))


class EMSNotNull12(EMSNotNull, NormalHandshake12):
    '''Send not empty extended master secret extension in TLSv1.2 hello'''
    pass


class EMSNotNull12PFS(EMSNotNull, NormalHandshake12PFS):
    '''Send not empty extended master secret extension in PFS TLSv1.2 hello'''
    pass


class CachedInfoNull(NormalHandshake):
    '''Send empty cached info extension in hello'''

    def make_cached_info_hello(self, value):
        cached_info_ext = Extension.create(
            extension_type=25,
            data=value)
        return self.make_hello([cached_info_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must include an array of complex objects
        sock.send(self.make_cached_info_hello(b''))


class CachedInfoNull12(CachedInfoNull, NormalHandshake12):
    '''Send empty cached info extension in TLSv1.2 hello'''
    pass


class CachedInfoNull12PFS(CachedInfoNull, NormalHandshake12PFS):
    '''Send empty cached info extension in PFS TLSv1.2 hello'''
    pass


class CachedInfoOverflow(CachedInfoNull):
    '''Send cached info extension with invalid size in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first two bytes are the size of the array, send too large one
        sock.send(self.make_cached_info_hello(b'\x00\x44'
                                               b'\x02'  # type cert_req
                                               b'\x20' +  # length of hash
                                               b'\xaf' * 32))  # hash


class CachedInfoOverflow12(CachedInfoOverflow, NormalHandshake12):
    '''Send cached info extension with invalid size in TLSv1.2 hello'''
    pass


class CachedInfoOverflow12PFS(CachedInfoOverflow, NormalHandshake12PFS):
    '''Send cached info extension with invalid size in PFS TLSv1.2 hello'''
    pass


class SessionTicketNull(NormalHandshake):
    '''Send empty session ticket extension in hello'''

    def make_session_ticket_hello(self, value):
        session_ticket_ext = Extension.create(
            extension_type=35,
            data=value)
        return self.make_hello([session_ticket_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first two bytes of the extension are the length, don't include any
        sock.send(self.make_session_ticket_hello(b''))


class SessionTicketNull12(SessionTicketNull, NormalHandshake12):
    '''Send empty session ticket extension in TLSv1.2 hello'''
    pass


class SessionTicketNull12PFS(SessionTicketNull, NormalHandshake12PFS):
    '''Send empty session ticket extension in PFS TLSv1.2 hello'''
    pass


class SessionTicketOverflow(SessionTicketNull):
    '''Send session ticket extension with too large length in hello'''

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # first two bytes are the length, send too large one
        sock.send(self.make_session_ticket_hello(b'\x02\x00' +
                                                  b'\xe7' * 0xff))


class SessionTicketOverflow12(SessionTicketOverflow, NormalHandshake12):
    '''Send session ticket extension with too large length in TLSv1.2 hello'''
    pass


class SessionTicketOverflow12PFS(SessionTicketOverflow, NormalHandshake12PFS):
    '''Send session ticket ext with too large length in PFS TLSv1.2 hello'''
    pass


class NPNNotNull(NormalHandshake):
    '''Send non empty NPN extension in hello'''

    def make_npn_hello(self, value):
        npn_ext = Extension.create(
            extension_type=13172,
            data=value)
        return self.make_hello([npn_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension has to be empty
        sock.send(self.make_npn_hello(b'\x04'))


class NPNNotNull12(NPNNotNull, NormalHandshake12):
    '''Send non empty NPN extension in TLSv1.2 hello'''
    pass


class NPNNotNull12PFS(NPNNotNull, NormalHandshake12PFS):
    '''Send non empty NPN extension in PFS TLSv1.2 hello'''
    pass


class TACKNotNull(NormalHandshake):
    '''Send not empty TACK extension in hello'''

    def make_tack_hello(self, value):
        tack_ext = Extension.create(
            extension_type=62208,
            data=value)
        return self.make_hello([tack_ext])

    def test(self, sock):
        logging.debug('Sending Client Hello...')
        # normal extension must be empty
        sock.send(self.make_tack_hello(b'\x08'))


class TACKNotNull12(TACKNotNull, NormalHandshake12):
    '''Send not empty TACK extension in TLSv1.2 hello'''
    pass


class TACKNotNull12PFS(TACKNotNull, NormalHandshake12PFS):
    '''Send not empty TACK extension in PFS TLSv1.2 hello'''
    pass
#!/usr/bin/python # Disable socks support in Jython # Note that changing these will invalidate many of the fingerprints # # Reusable standard elements # # Check if we're using socks # Do starttls if relevant # return s.makefile('rw', 0) # Check if there is anything following the server done # If no data then we're done (the server hasn't sent anything further) # we allow 500ms to give the followup time to arrive # TODO: Not sure that recording the record layer version is worth it? # response += 'error:%s|' % errno.errorcode[e.errno] # A single handshake record can contain multiple handshake messages A normal handshake Normal handshake with PFS ciphersuites Normal TLSv1.1 handshake Normal TLSv1.1 handshake Normal TLSv1.2 handshake Normal TLSv1.2 handshake with PFS ciphersuites TLSv1.2 with PFS ciphers with a TLSv1.3 version (invalid TLSv1.3) #hexdump(record.bytes) Send session ID that is too long # session ID is up to 32 bytes long Send session ID that is too long # session ID is up to 32 bytes long Send session ID that is too long in TLSv1.2 hello Send session ID that is too long in PFS TLSv1.2 hello Send client hello with length field of ciphers that is invalid (odd) As with InvalidCiphersLength but with TLSv1.2 helo As with InvalidCiphersLength but with PFS TLSv1.2 hello Send client hello with length of extensions filed truncated As with InvalidExtLength but in TLSv1.2 hello As with InvalidExtLength but in PFS TLSv1.2 hello Send hello with data length lower than stated size # extensions length, just one byte # extension ID - secure renego indication # secure renego indication ext length # valid payload for extension As in ExtensionsUnderflow but in TLSv1.2 hello As in ExtensionsUnderflow but in PFS TLSv1.2 hello Send hello with no compression methods As with EmptyCompression but in TLSv1.2 hello As with EmptyCompression but in PFS TLSv1.2 hello Send hello with no support for uncompressed communication As with CompressOnly but in TLSv1.2 hello As with CompressOnly but in PFS TLSv1.2 hello Two client hellos Two client hellos, TLSv1.2 Two client hellos, TLSv1.2 w/PFS ciphers Send a hello then change cipher spec Send TLSv1.2 hello then change cipher spec Send PFS TLSv1.2 hello then change cipher spec Send a hello then hello request Send a TLSv1.2 hello then hello request Send a PFS TLSv1.2 hello then hello request Send a hello then an empty change cipher spec Send TLSv1.2 hello then an empty change cipher spec Send PFS TLSv1.2 hello then an empty change cipher spec An invalid handshake message #hexdump(record.bytes) Try connecting with ECC cipher suites only #hexdump(record.bytes) Try to send a heartbeat message #hexdump(record.bytes) Try to send a heartbeat message in TLSv1.2 connection Try to send a hearbeat message in PFS TLSv1.2 connection Try to send a heartbleed attack #hexdump(record.bytes) Try to send a heartbleed attack in TLSv1.2 Try to send a heartbleed attack in TLSv1.2 Set a high TLS version in the record #hexdump(record.bytes) Set a high TLS version in the record of TLSv1.2 hello Set a high TLS version in the record of PFS TLSv1.2 hello Set a very high TLS version in the record #hexdump(record.bytes) Set a very high TLS version in the record of TLSv1.2 hello Set a very high TLS version in the record of PFS TLSv1.2 hello Set a zero version in the record #hexdump(record.bytes) Set a zero version in the record of TLSv1.2 hello Set a zero version in the record of PFS TLSv1.2 hello Set a high version in the hello #hexdump(record.bytes) Set a high version in a hello with more ciphers Set a high version in a hello with PFS ciphers Set a very high version in the hello Set a very high version in the hello with more ciphers Set a very high version in the hello with PFS ciphers Set a zero version in the hello #hexdump(record.bytes) Use an invalid content type in the record #hexdump(record.bytes) Make the record length exceed the stated one #hexdump(record.bytes) Make the record shorter than the specified length #hexdump(record.bytes) Send an empty record then the hello #hexdump(record.bytes) Send an empty record then TLSv1.2 hello Send and empty record then PFS TLSv1.2 hello Send two invalid messages Split the hello over two records #hexdump(record.bytes) Split the TLS1.2 hello over two records #hexdump(record.bytes) Split the TLS1.2 PFS hello over two records #hexdump(record.bytes) Split the hello over two packets # sock.flush() Split the TLS1.2 hello over two packets Split the TLS1.2 PFS hello over two packets Send an empty cipher list #hexdump(record.bytes) Send and empty cipher list in TLSv1.2 hello Send a server name indication for a non-matching name Send a server name indication for non-matching name in TLSv1.2 hello Send a SNI extension for non-matching name in PFS TLSv1.2 hello Send a server name indication with a long name Send a server name indication with a long name in TLSv1.2 hello Send a server name indication with a long name in PFS TLSv1.2 hello Send a server name indication with an empty name Send a server name indication with an empty name in TLSv1.2 hello Send a server name indication with an empty name in PFS TLSv1.2 hello Send server name indication with two names, one wrong Send server name indication with two names, one wrong in TLS1.2 hello As in SNIOneWrong but in PFS TLS1.2 hello Send server name indication with two names, one not of host_name type # only type 0 (HostName) is defined, any other should be ignored As with SNIWithDifferentType but in TLSv1.2 hello As with SNIWithDifferentType but in PFS TLSv1.2 hello Send hello like in SNIWithDifferentType but reverse order of names # only type 0 (HostName) is defined, any other should be ignored As with SNIDifferentTypeRev but in TLSv1.2 hello As with SNIDifferentTypeRev but in PFS TLSv1.2 hello Send server name indication with data length exceeding stated size # first four bytes are the header, last one we truncate to exceed size as with SNIOverflow but in TLSv1.2 hello as with SNIOverflow but in TLSv1.2 hello Send server name indication with data length smaller than size inside # first four bytes are the header As with SNIUnderflow, but in TLSv1.2 hello As with SNIUnderflow, but in PFS TLSv1.2 hello Send secure renegotiation with data length exceeding stated size # first byte of secure renegotiation extension specifies the # length of the array of bytes in it, but don't provide the # required amount As with SecureRenegotOverflow, inside TLSv1.2 hello As with SecureRenegoOverflow, inside TLSv1.2 PFS hello Send secure renegotiation with data length lower than stated size # again, first byte specifies zero-length array, rest of bytes # are just padding to make the extension large As with SecureRenegoUnderflow, inside TLSv1.2 hello As with SecureRenegoUnderflow, inside PFS TLSv1.2 hello Send secure renegotiation with renegotiation payload # send a correctly formatted extension, but with a non-empty # payload (indicating renegotiated connection) Send secure renegotiation with renegotiation payload in TLSv1.2 hello As with SecureRenegoNonEmpty12, but with PFS ciphers Send secure renegotiation extension that is completely empty # While the proper formatting is to send an empty array, and not # no array, some servers still accept it As with SecureRenegoNull, but in TLSv1.2 hello As with SecureRenegoNull, but in PFS TLSv1.2 hello Send maximum fragment length extension that is completely empty # normal extension needs a single byte value, don't provide it As with MaxFragmentNull, but in TLSv1.2 hello As with MaxFragmentNull, but in PFS TLSv1.2 hello Send maximum fragment length extension with invalid value # valid values are between 1 and 4 inclusive As with MaxFragmentInvalid, but in TLSv1.2 hello As with MaxFragmentInvalid, but in PFS TLSv1.2 hello Send client certificate URL indication extension that is not empty # correctly formatted does not include any data As with ClientCertURLsNotNull, but in TLSv1.2 hello As with ClientCertURLsNotNull, but in PFS TLSv1.2 hello Send trusted CA keys extension with completely empty payload # normal formatting is a complex structure As with TrustedCANull but in TLSv1.2 hello As with TrustedCANull, but in PFS TLSv1.2 hello Send trusted CA keys extension smaller than length inside indicates # in a normal structure, the first two bytes are the overall length # of list with extension data # a typical payload includes type (1B) and sha1 hash (20B) As with TrustedCAOverflow but in TLSv1.2 hello As with TrustedCAOverflow but in PFS TLSv1.2 hello Send trusted CA keys extension larger than length inside indicates # type key_sha1_hash + sha1 hash (20 bytes) # payload has a 2 byte length and then an array of items, # add null byte at end to cause the underflow As with TrustedCAUnderflow but in TLSv1.2 hello As with TrustedCAUnderflow but in PFS TLSv1.2 hello Send a truncated HMAC extension with a non empty payload # properly formatted extension has no data at all As with TruncatedHMACNotNull but in TLSv1.2 hello As with TruncatedHMACNotNull but in PFS TLSv1.2 hello Send status request extension with empty payload # normally the status request is a complex structure, don't include # it As with OCSPNull but in TLSv1.2 hello As with OCSPNull but in PFS TLSv1.2 hello Send status request ext smaller than the length inside indicates # the request has three fields - type (one byte) and two arrays # with 2 byte long headers, truncate the second length header As with OCSPOverflow but in TLSv1.2 hello As with OCSPOverflow but in PFS TLSv1.2 hello Send status request ext larger than the length inside indicate # correctly formed request, two extra zero bytes As with OCSPUnderflow but in TLSv1.2 hello As with OCSPUnderflow but in PFS TLSv1.2 hello Duplicate secure renegotiation extension # correct Client Hello messages must not contain two extensions # of the same type Duplicate secure renegotiation extension in TLSv1.2 hello Duplicate secure renegotiation extension in PFS TLSv1.2 hello Send empty user mapping extension in hello # extension consists of an array and the array needs at least one # element, don't send any Send empty user mapping extension in TLSv1.2 hello Send empty user mapping extension in PFS TLSv1.2 hello Send user mapping extension with length longer than present in hello # extension consists of an array and the array needs at least one # element, send the length of array (one byte) longer than payload size As with UserMappingOverflow but in TLSv1.2 hello As with UserMappingOverflow but in PFS TLSv1.2 hello Send empty client authz extension in hello # normal extension has an array, don't send anything Send empty client authz extension in TLSv1.2 hello Send empty client authz extension in PFS TLSv1.2 hello Send client authz extension with length longer than data in hello # normal extension has one byte length as first element then # the array, make the array length longer than real payload As with ClientAuthzOverflow but in TLSv1.2 hello As with ClientAuthzOverflow but in PFS TLSv1.3 hello Send empty server authz extension in hello Send empty server authz extension in TLSv1.2 hello Send empty server authz extension in PFS TLSv1.2 hello Send server authz extension with length longer than data in hello As with ServerAuthzOverflow but in TLSv1.2 hello As with ServerAuthzOverflow but in PFS TLSv1.2 hello Send empty cert type extension in hello # normal extension has an array, don't send anything Send empty cert type extension in TLSv1.2 hello Send empty cert type extension in PFS TLSv1.2 hello Send cert type extension with too large length in hello # first byte is a length of array, send invalid one Send cert type extension with too large length in TLSv1.2 hello Send cert type extension with too large length in PFS TLSv1.2 hello Send empty supported groups extension in hello # normal extension has an array, don't send anything Send empty supported groups extension in TLSv1.2 hello Send empty supported groups extension in PFS TLSv1.2 hello Send supported groups extension with invalid length in hello # normal extension has a two byte length and two byte elements, # truncate the second element Send supported groups extension with invalid length in TLSv1.2 hello As with SupportedGroupsOddLen but in PFS TLSv1.2 hello Send supported groups extension with length larger than data # normal extension has a two byte length and two byte elements, # truncate the whole second element As with SupportedGroupsOverflow but in TLSv1.2 hello As with SupportedGroupsOverflow but in PFS TLSv1.2 hello Send empty ec point formats extension in hello # normal extension has an array, don't send anything Send empty ec point formats extension in TLSv1.2 hello Send empty ec point formats extension in PFS TLSv1.2 hello Send ec point formats extension with length larger than data in hello # first byte is the length of array, send too large one As with ECPointFormatsOverflow but in TLSv1.2 hello As with ECPointFormatsOverflow but in PFS TLSv1.2 hello Send ec point formats extension without uncompressed format # the uncompressed format is mandatory, send extension without it As with ECPointFormatsCompOnly but in TLSv1.2 hello As with ECPointFormatsCompOnly but in PFS TLS v1.2 hello Send empty srp extension in hello # normally the extension has client's identity, don't include any Send empty srp extension in TLSv1.2 hello Send empty srp extension in PFS TLSv1.2 hello Send srp extension with too large length in hello # first byte is the length, send too large Send srp extension with too large length in TLSv1.2 hello Send srp extension with too large length in PFS TLSv1.2 hello Send empty signature algorithms extension in hello # normal extension has an array, don't send anything Send empty signature algorithms extension in TLSv1.2 hello Send empty signature algorithms extension in PFS TLSv1.2 hello Send signature algorithms extensions with invalid length in hello # normal extension has two byte long elements, truncate the last one As in SigAlgsOddLen but in TLSv1.2 hello As in SigAlgsOddLen but in PFS TLSv1.2 hello Send signature algorithms extension with too large length in hello # the first two bytes are the length of the array, send too large one As in SigAlgsOverflow but in TLSv1.2 hello As in SigAlgsOverflow but in PFS TLSv1.2 hello Send empty use srtp extension in hello # normal extension has an array, don't send anything Send empty use srtp extension in TLSv1.2 hello Send empty use srtp extension in PFS TLSv1.2 hello Send use srtp extension with too large length in hello # the extension starts with a two byte length of two-byte elements # and the second array is optional with a simple binary string Send use srtp extension with too large length in TLSv1.2 hello Send use srtp extension with too large length in PFS TLSv1.2 hello Send use srtp extension with length larger than payload # the extension has two arrays, one has a two byte length the other # a one byte length, make the first array longer than payload Send use srtp extension with length larger than payload in TLSv1.2 As in UseSrtpOverflow but in PFS TLSv1.2 hello Send empty heartbeat extension in hello # the extension is a single byte value, don't include it Send empty heartbeat extension in TLSv1.2 hello Send empty heartbeat extension in PFS TLSv1.2 hello Send heartbeat extension with invalid value in hello # the valid values are 1 and 2, send something else Send heartbeat extension with invalid value in TLSv1.2 hello Send heartbeat extension with invalid value in PFS TLSv1.2 hello Send empty ALPN extension in hello # valid extension has an array, don't send anything Send empty APLN extension in TLSv1.2 hello Send empty ALPN extension in PFS TLSv1.2 hello Send ALPN extension with only unknown protocol in hello # the extension is an array of arrays, the external array has # two byte length header, the internal arrays have one byte length Send ALPN extension with only unknown protocol in TLSv1.2 hello Send ALPN extension with only unknown protocol in PFS TLSv1.2 hello Send ALPN extension with too large length in hello # the extension is an array of arrays, the external array has # two byte length header, the internal arrays have one byte length # make the external length too large Send ALPN extension with too large length in TLSv1.2 hello Send ALPN extension with too large length in PFS TLSv1.2 hello Send empty OCSPv2 staple extension in hello # normal encoding has a list of complex items, don't include anything Send empty OCSPv2 staple extension in TLSv1.2 hello Send empty OCSPv2 staple extension in PFS TLSv1.2 hello Send OCSPv2 staple extension with too large length in hello # overall length of extension (too large) # first request type (ocsp) # request length # responder ID list length # request extensions list length # second request type (ocsp_multi) # request length # responder ID list length # request extensions list length Send OCSPv2 staple extension with too large length in TLSv1.2 hello As with OCSPv2Overflow but in PFS TLSv1.2 hello Send hello with signed certificate timestamp that is not empty # valid extension should be empty As with SignedCertTSNotNull but in TLSv1.2 hello As with SignedCertTSNotNull but in PFS TLSv1.2 hello Send empty client certificate type extension in hello # valid extension has an array Send empty client certificate type extension in TLSv1.2 hello Send empty client certificate type extension in PFS TLSv1.2 hello Send client certificate type extension with too large length in hello # first byte is the length of the array, send too large As with ClientCertTypeOverflow, but in TLSv1.2 hello As with ClientCertTypeOverflow but in PFS TLSv1.2 hello Send empty server certificate type extension in hello # valid extension has an array Send empty server certificate type extension in TLSv1.2 hello Send empty server certificate type extension in PFS TLSv1.2 hello Send server certificate type extension with too large length in hello # first byte is the length of the array, send too large As with ServerCertTypeOverflow, but in TLSv1.2 hello As with ServerCertTypeOverflow but in PFS TLSv1.2 hello Send empty padding extension in hello # there is no invalid encoding of extension, send an empty one Send empty padding extension in TLSv1.2 hello Send empty padding extension in PFS TLSv1.2 hello Use padding extension to send 300 byte large hello # normal hello is 64 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 300 byte large TLSv1.2 hello # TLSv1.2 hello is 88 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 300 byte large PFS TLSv1.2 hello # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 600 byte large hello # normal hello is 64 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 600 byte large TLSv1.2 hello # TLSv1.2 hello is 88 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 600 byte large PFS TLSv1.2 hello # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 16384 byte large hello # normal hello is 64 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes # 16384 is the largest size that can be sent in a single record layer Use padding extension to send 16384 byte large TLSv1.2 hello # TLSv1.2 hello is 88 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 16384 byte large PFS TLSv1.2 hello # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 16385 byte large hello # hello is 64 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 16385 byte large TLSv1.2 hello # TLSv1.2 hello is 88 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 16385 byte large PFS TLSv1.2 hello # PFS TLSv1.2 hello is 144 byte large with all headers, 5 of which are # record layer overhead, extensions length is already included # but extension id and extension length is not, totalling 4 bytes Use padding extension to send 16387 byte large hello Use padding extension to send 16387 byte large TLSv1.2 hello Use padding extension to send 16387 byte large PFS TLSv1.2 hello Use padding extension to send 16389 byte large hello Use padding extension to send 16389 byte large TLSv1.2 hello Use padding extension to send 16389 byte large PFS TLSv1.2 hello Use padding extension to send 17520 byte large hello Use padding extension to send 17520 byte large TLSv1.2 hello Use padding extension to send 17520 byte large PFS TLSv1.2 hello Send not empty encrypt then mac extension in hello # normal extension must be empty Send not empty encrypt then mac extension in TLSv1.2 hello Send not empty encrypt then mac extension in PFS TLSv1.2 hello Send not empty extended master secret extension in hello # normal extension must be empty Send not empty extended master secret extension in TLSv1.2 hello Send not empty extended master secret extension in PFS TLSv1.2 hello Send empty cached info extension in hello # normal extension must include an array of complex objects Send empty cached info extension in TLSv1.2 hello Send empty cached info extension in PFS TLSv1.2 hello Send cached info extension with invalid size in hello # first two bytes are the size of the array, send too large one # type cert_req # length of hash # hash Send cached info extension with invalid size in TLSv1.2 hello Send cached info extension with invalid size in PFS TLSv1.2 hello Send empty session ticket extension in hello # first two bytes of the extension are the length, don't include any Send empty session ticket extension in TLSv1.2 hello Send empty session ticket extension in PFS TLSv1.2 hello Send session ticket extension with too large length in hello # first two bytes are the length, send too large one Send session ticket extension with too large length in TLSv1.2 hello Send session ticket ext with too large length in PFS TLSv1.2 hello Send non empty NPN extension in hello # normal extension has to be empty Send non empty NPN extension in TLSv1.2 hello Send non empty NPN extension in PFS TLSv1.2 hello Send not empty TACK extension in hello # normal extension must be empty Send not empty TACK extension in TLSv1.2 hello Send not empty TACK extension in PFS TLSv1.2 hello