def test__getNextRecord_with_multiple_messages_in_single_record(self):

        mock_sock = MockSocket(
            bytearray(b'\x16' +  # handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x35' +  # length
                      # server hello
                      b'\x02' +  # type - server hello
                      b'\x00\x00\x26' +  # length
                      b'\x03\x03' +  # TLSv1.2
                      b'\x01' * 32 +  # random
                      b'\x00' +  # session ID length
                      b'\x00\x2f' +  # cipher suite selected
                      b'\x00' +  # compression method
                      # certificate
                      b'\x0b' +  # type - certificate
                      b'\x00\x00\x03'  # length
                      b'\x00\x00\x00'  # length of certificates
                      # server hello done
                      b'\x0e' +  # type - server hello done
                      b'\x00\x00\x00'  # length
                      ))

        record_layer = TLSRecordLayer(mock_sock)

        results = []
        for result in record_layer._getNextRecord():
            if result in (0, 1):
                raise Exception("blocking")
            else:
                results.append(result)
                if len(results) == 3:
                    break

        header, p = results[0]

        self.assertIsInstance(header, RecordHeader3)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(42, len(p.bytes))
        self.assertEqual(HandshakeType.server_hello, p.bytes[0])

        # XXX generator stops as soon as a message was read
        #self.assertEqual(1, len(results))
        #return

        header, p = results[1]

        self.assertIsInstance(header, RecordHeader3)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(7, len(p.bytes))
        self.assertEqual(HandshakeType.certificate, p.bytes[0])

        header, p = results[2]

        self.assertIsInstance(header, RecordHeader3)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(4, len(p.bytes))
        self.assertEqual(HandshakeType.server_hello_done, p.bytes[0])
    def test__getNextRecord_with_multiple_messages_in_single_record(self):

        mock_sock = MockSocket(bytearray(
            b'\x16' +           # handshake
            b'\x03\x03' +       # TLSv1.2
            b'\x00\x35' +       # length
            # server hello
            b'\x02' +           # type - server hello
            b'\x00\x00\x26' +   # length
            b'\x03\x03' +       # TLSv1.2
            b'\x01'*32 +        # random
            b'\x00' +           # session ID length
            b'\x00\x2f' +       # cipher suite selected
            b'\x00' +           # compression method
            # certificate
            b'\x0b' +           # type - certificate
            b'\x00\x00\x03'     # length
            b'\x00\x00\x00'     # length of certificates
            # server hello done
            b'\x0e' +           # type - server hello done
            b'\x00\x00\x00'     # length
            ))

        record_layer = TLSRecordLayer(mock_sock)

        results = []
        for result in record_layer._getNextRecord():
            if result in (0,1):
                raise Exception("blocking")
            else:
                results.append(result)
                if len(results) == 3:
                    break

        header, p = results[0]

        self.assertIsInstance(header, RecordHeader3)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(42, len(p.bytes))
        self.assertEqual(HandshakeType.server_hello, p.bytes[0])

        # XXX generator stops as soon as a message was read
        #self.assertEqual(1, len(results))
        #return

        header, p = results[1]

        self.assertIsInstance(header, RecordHeader3)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(7, len(p.bytes))
        self.assertEqual(HandshakeType.certificate, p.bytes[0])

        header, p = results[2]

        self.assertIsInstance(header, RecordHeader3)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(4, len(p.bytes))
        self.assertEqual(HandshakeType.server_hello_done, p.bytes[0])
    def test__getNextRecord_with_blocking_socket(self):
        mockSock = mock.MagicMock()
        mockSock.recv.side_effect = socket.error(errno.EWOULDBLOCK)

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        self.assertEqual(0, next(gen))
    def test__getNextRecord_with_SSL2_record_with_incomplete_header(self):
        mockSock = MockSocket(bytearray(b"\x80"))  # tag

        sock = TLSRecordLayer(mockSock)

        # XXX using private method
        for result in sock._getNextRecord():
            break

        self.assertEqual(0, result)
    def test__getNextRecord_with_not_complete_SSL2_record(self):
        mockSock = MockSocket(bytearray(b"\x80" + b"\x04" + b"\x00" * 3))  # tag  # length

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            break

        self.assertEqual(0, result)
    def test__getNextRecord_with_blocking_socket(self):
        mockSock = mock.MagicMock()
        mockSock.recv.side_effect = socket.error(errno.EWOULDBLOCK)

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        self.assertEqual(0, next(gen))
    def test__getNextRecord_with_empty_socket(self):
        mockSock = mock.MagicMock()
        mockSock.recv.side_effect = [bytearray(0)]

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSAbruptCloseError):
            next(gen)
    def test__getNextRecord_with_errored_out_socket(self):
        mockSock = mock.MagicMock()
        mockSock.recv.side_effect = socket.error(errno.ETIMEDOUT)

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(socket.error):
            next(gen)
    def test__getNextRecord_with_empty_socket(self):
        mockSock = mock.MagicMock()
        mockSock.recv.side_effect = [bytearray(0)]

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSAbruptCloseError):
            next(gen)
    def test__getNextRecord_with_errored_out_socket(self):
        mockSock = mock.MagicMock()
        mockSock.recv.side_effect = socket.error(errno.ETIMEDOUT)

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(socket.error):
            next(gen)
    def test__getNextRecord_with_SSL2_record_with_incomplete_header(self):
        mockSock = MockSocket(bytearray(b'\x80'  # tag
                                        ))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method
        for result in sock._getNextRecord():
            break

        self.assertEqual(0, result)
    def test__getNextRecord_with_empty_handshake(self):

        mock_sock = MockSocket(bytearray(b"\x16" + b"\x03\x03" + b"\x00\x00"))  # handshake  # TLSv1.2  # length

        record_layer = TLSRecordLayer(mock_sock)

        with self.assertRaises(TLSLocalAlert):
            for result in record_layer._getNextRecord():
                if result in (0, 1):
                    raise Exception("blocking socket")
                else:
                    break
    def test__getNextRecord_with_not_complete_SSL2_record(self):
        mockSock = MockSocket(
            bytearray(b'\x80' +  # tag
                      b'\x04' +  # length
                      b'\x00' * 3))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            break

        self.assertEqual(0, result)
    def test__getNextRecord_with_malformed_record(self):
        mockSock = MockSocket(
            bytearray(b"\x01" + b"\x03\x03" + b"\x00\x01" + b"\x00")  # wrong type  # TLSv1.2  # length
        )

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSLocalAlert) as context:
            next(gen)

        self.assertEqual(str(context.exception), "illegal_parameter")
    def test__getNextRecord_with_too_big_record(self):
        mockSock = MockSocket(
            bytearray(b"\x16" + b"\x03\x03" + b"\xff\xff" + b"\x00" * 65536)  # type - handshake  # TLSv1.2  # length
        )

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSLocalAlert) as context:
            next(gen)

        self.assertEqual(str(context.exception), "record_overflow")
    def test__getNextRecord_with_empty_handshake(self):

        mock_sock = MockSocket(
            bytearray(b'\x16' +  # handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x00'  # length
                      ))

        record_layer = TLSRecordLayer(mock_sock)

        with self.assertRaises(TLSLocalAlert):
            for result in record_layer._getNextRecord():
                if result in (0, 1):
                    raise Exception("blocking socket")
                else:
                    break
    def test__getNextRecord_with_malformed_record(self):
        mockSock = MockSocket(
            bytearray(b'\x01' +  # wrong type
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x01' +  # length
                      b'\x00'))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSLocalAlert) as context:
            next(gen)

        self.assertEqual(str(context.exception), "illegal_parameter")
    def test__getNextRecord_with_too_big_record(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\xff\xff' +  # length
                      b'\x00' * 65536))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSLocalAlert) as context:
            next(gen)

        self.assertEqual(str(context.exception), "record_overflow")
    def test__getNextRecord_with_trickling_socket(self):
        mockSock = MockSocket(
            bytearray(b"\x16" + b"\x03\x03" + b"\x00\x04" + b"\x00" * 4),  # type - handshake  # TLSv1.2  # length
            maxRet=1,
        )

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertEqual(bytearray(4), data)
    def test__getNextRecord(self):
        mockSock = MockSocket(
            bytearray(b"\x16" + b"\x03\x03" + b"\x00\x04" + b"\x00" * 4)  # type - handshake  # TLSv1.2  # length
        )
        sock = TLSRecordLayer(mockSock)
        sock.version = (3, 3)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertEqual(data, bytearray(4))
        self.assertEqual(header.type, ContentType.handshake)
        self.assertEqual(header.version, (3, 3))
        self.assertEqual(header.length, 0)
    def test__getNextRecord_with_SSL2_record(self):
        mockSock = MockSocket(bytearray(b"\x80" + b"\x04" + b"\x00" * 4))  # tag  # length

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertTrue(header.ssl2)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(4, header.length)
        self.assertEqual((2, 0), header.version)

        self.assertEqual(bytearray(4), data)
    def test__getNextRecord_with_trickling_socket(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x04' +  # length
                      b'\x00' * 4),
            maxRet=1)

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertEqual(bytearray(4), data)
    def test__getNextRecord_with_slow_socket(self):
        mockSock = MockSocket(
            bytearray(b"\x16" + b"\x03\x03" + b"\x00\x04" + b"\x00" * 4),  # type - handshake  # TLSv1.2  # length
            maxRet=1,
            blockEveryOther=True,
        )

        sock = TLSRecordLayer(mockSock)

        gotRetry = False
        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                gotRetry = True
            else:
                break

        header, data = result
        data = data.bytes

        self.assertTrue(gotRetry)
        self.assertEqual(bytearray(4), data)
    def test__getNextRecord(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x04' +  # length
                      b'\x00' * 4))
        sock = TLSRecordLayer(mockSock)
        sock.version = (3, 3)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertEqual(data, bytearray(4))
        self.assertEqual(header.type, ContentType.handshake)
        self.assertEqual(header.version, (3, 3))
        self.assertEqual(header.length, 0)
    def test__getNextRecord_with_slow_socket(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x04' +  # length
                      b'\x00' * 4),
            maxRet=1,
            blockEveryOther=True)

        sock = TLSRecordLayer(mockSock)

        gotRetry = False
        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                gotRetry = True
            else:
                break

        header, data = result
        data = data.bytes

        self.assertTrue(gotRetry)
        self.assertEqual(bytearray(4), data)
    def test__getNextRecord_with_SSL2_record(self):
        mockSock = MockSocket(
            bytearray(b'\x80' +  # tag
                      b'\x04' +  # length
                      b'\x00' * 4))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertTrue(header.ssl2)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(4, header.length)
        self.assertEqual((2, 0), header.version)

        self.assertEqual(bytearray(4), data)