Example #1
0
    def test_unseal_message_incorrect_checksum(self):
        test_flags = ntlmv2_negotiate_flags
        test_session_security = SessionSecurity(test_flags, session_base_key)
        test_server_session_security = SessionSecurity(test_flags, session_base_key, source="server")
        test_message, test_signature = test_server_session_security.wrap(plaintext_data)
        # Overwrite signature to produce a bad checksum
        test_signature = HexToByte('01 00 00 00 b1 98 b8 47 ce 7c 58 07 00 00 00 00')

        with self.assertRaises(Exception) as context:
            test_session_security.unwrap(test_message, test_signature)

        self.assertTrue('The signature checksum does not match, message has been altered' in context.exception.args)
Example #2
0
    def test_unseal_message_incorrect_seq_num(self):
        test_flags = ntlmv2_negotiate_flags
        test_session_security = SessionSecurity(test_flags, session_base_key)
        test_server_session_security = SessionSecurity(test_flags, session_base_key, source="server")
        test_message, test_signature = test_server_session_security.wrap(plaintext_data)
        # Overwrite signature to produce a bad checksum
        test_signature = HexToByte('01 00 00 00 b2 98 b8 47 ce 7c 58 07 00 00 00 01')

        with self.assertRaises(Exception) as context:
            test_session_security.unwrap(test_message, test_signature)

        self.assertTrue('The signature sequence number does not match up, message not received in the correct sequence' in context.exception.args)
Example #3
0
    def test_unseal_message_ntlm2_key_exchange(self):
        test_flags = ntlmv2_negotiate_flags
        test_session_security = SessionSecurity(test_flags, session_base_key)
        test_server_session_security = SessionSecurity(test_flags, session_base_key, source="server")
        test_message, test_signature = test_server_session_security.wrap(plaintext_data)

        expected_data = plaintext_data

        actual_data = test_session_security.unwrap(test_message, test_signature)

        assert actual_data == expected_data
    def test_unseal_message_incorrect_checksum(self):
        negotiate_flags = 3800728116
        session_key = b"\xff" * 16
        test_session_security = SessionSecurity(negotiate_flags, session_key)
        test_server_session_security = SessionSecurity(negotiate_flags,
                                                       session_key,
                                                       source="server")

        plaintext_data = b"\x50\x00\x6c\x00\x61\x00\x69\x00" \
                         b"\x6e\x00\x74\x00\x65\x00\x78\x00" \
                         b"\x74\x00"
        test_message, test_signature = \
            test_server_session_security.wrap(plaintext_data)
        # Overwrite signature to produce a bad checksum
        test_signature = b"\x01\x00\x00\x00\xb1\x98\xb8\x47" \
                         b"\xce\x7c\x58\x07\x00\x00\x00\x00"

        with pytest.raises(Exception) as exc:
            test_session_security.unwrap(test_message, test_signature)
        assert str(exc.value) == "The signature checksum does not match, " \
                                 "message has been altered"
Example #5
0
    def test_verify_sign_no_unseal_message(self):
        test_flags = ntlmv2_negotiate_flags - NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL
        test_session_security = SessionSecurity(test_flags, session_base_key)
        test_server_session_security = SessionSecurity(test_flags, session_base_key, source="server")
        test_message, test_signature = test_server_session_security.wrap(plaintext_data)

        expected_data = plaintext_data

        actual_data = test_session_security.unwrap(test_message, test_signature)

        assert test_message == expected_data
        assert actual_data == expected_data
    def test_unseal_message_incorrect_seq_num(self):
        negotiate_flags = 3800728116
        session_key = b"\xff" * 16
        test_session_security = SessionSecurity(negotiate_flags, session_key)
        test_server_session_security = SessionSecurity(negotiate_flags,
                                                       session_key,
                                                       source="server")

        plaintext_data = b"\x50\x00\x6c\x00\x61\x00\x69\x00" \
                         b"\x6e\x00\x74\x00\x65\x00\x78\x00" \
                         b"\x74\x00"
        test_message, test_signature = \
            test_server_session_security.wrap(plaintext_data)
        # Overwrite signature to produce a bad checksum
        test_signature = test_signature[:-4] + b"\x01\x00\x00\x00"

        with pytest.raises(Exception) as exc:
            test_session_security.unwrap(test_message, test_signature)

        assert str(exc.value) == "The signature sequence number does not " \
                                 "match up, message not received in the " \
                                 "correct sequence"
    def test_unseal_message_ntlm2_key_exchange(self):
        negotiate_flags = 3800728116
        session_key = b"\xff" * 16
        test_session_security = SessionSecurity(negotiate_flags, session_key)
        test_server_session_security = SessionSecurity(negotiate_flags,
                                                       session_key,
                                                       source="server")

        plaintext_data = b"\x50\x00\x6c\x00\x61\x00\x69\x00" \
                         b"\x6e\x00\x74\x00\x65\x00\x78\x00" \
                         b"\x74\x00"
        test_message, test_signature = \
            test_server_session_security.wrap(plaintext_data)

        expected_data = plaintext_data
        actual_data = test_session_security.unwrap(test_message,
                                                   test_signature)
        assert actual_data == expected_data
    def test_unseal_message_ntlm2_no_key_exchange(self):
        negotiate_flags = 2181726771
        session_key = b"\xeb\x93\x42\x9a\x8b\xd9\x52\xf8" \
                      b"\xb8\x9c\x55\xb8\x7f\x47\x5e\xdc"
        test_session_security = SessionSecurity(negotiate_flags, session_key)
        test_server_session_security = SessionSecurity(negotiate_flags,
                                                       session_key,
                                                       source="server")

        plaintext_data = b"\x50\x00\x6c\x00\x61\x00\x69\x00" \
                         b"\x6e\x00\x74\x00\x65\x00\x78\x00" \
                         b"\x74\x00"
        test_message, test_signature = \
            test_server_session_security.wrap(plaintext_data)

        expected_data = plaintext_data
        actual_data = test_session_security.unwrap(test_message,
                                                   test_signature)
        assert actual_data == expected_data
    def test_verify_sign_no_unseal_message(self):
        negotiate_flags = 3800728116 - NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL
        session_key = b"\x55" * 16
        test_session_security = SessionSecurity(negotiate_flags, session_key)
        test_server_session_security = SessionSecurity(negotiate_flags,
                                                       session_key,
                                                       source="server")

        plaintext_data = b"\x50\x00\x6c\x00\x61\x00\x69\x00" \
                         b"\x6e\x00\x74\x00\x65\x00\x78\x00" \
                         b"\x74\x00"
        test_message, test_signature = \
            test_server_session_security.wrap(plaintext_data)

        expected_data = plaintext_data
        actual_data = test_session_security.unwrap(test_message,
                                                   test_signature)
        assert test_message == expected_data
        assert actual_data == expected_data
Example #10
0
    def test_wrap_unwrap(self):
        context = NTLMContext("username", "password", None)
        context.init_context()

        gen = context.step()
        next(gen)
        msg2 = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
               b"\x02\x00\x00\x00\x2f\x82\x88\xe2" \
               b"\x38\x00\x00\x00\x33\x82\x8a\xe2" \
               b"\x01\x23\x45\x67\x89\xab\xcd\xef" \
               b"\x00\x00\x00\x00\x00\x00\x00\x00" \
               b"\x24\x00\x24\x00\x44\x00\x00\x00" \
               b"\x06\x00\x70\x17\x00\x00\x00\x0f" \
               b"\x53\x00\x65\x00\x72\x00\x76\x00" \
               b"\x65\x00\x72\x00\x02\x00\x0c\x00" \
               b"\x44\x00\x6f\x00\x6d\x00\x61\x00" \
               b"\x69\x00\x6e\x00\x01\x00\x0c\x00" \
               b"\x53\x00\x65\x00\x72\x00\x76\x00" \
               b"\x65\x00\x72\x00\x00\x00\x00\x00"
        gen.send(msg2)

        plaintext_client = b"client"
        plaintext_server = b"server"
        server_sec = SessionSecurity(
            context._context._session_security.negotiate_flags,
            context._context._session_security.exported_session_key, "server"
        )

        client_header, client_wrap = context.wrap(plaintext_client)
        assert client_header.startswith(b"\x01\x00\x00\x00")
        assert len(client_header) == 16
        assert client_wrap != plaintext_client

        client_plaintext = server_sec.unwrap(client_wrap, client_header)
        assert client_plaintext == plaintext_client

        server_wrap, server_header = server_sec.wrap(plaintext_server)
        assert server_header.startswith(b"\x01\x00\x00\x00")
        assert len(server_header) == 16
        assert server_wrap != plaintext_server

        server_plaintext = context.unwrap(server_header, server_wrap)
        assert server_plaintext == plaintext_server
    def test_unseal_message_ntlm1(self):
        negotiate_flags = 3791815219
        session_key = b"\xd8\x72\x62\xb0\xcd\xe4\xb1" \
                      b"\xcb\x74\x99\xbe\xcc\xcd\xf1" \
                      b"\x07\x84"
        test_session_security = SessionSecurity(negotiate_flags, session_key)
        test_server_session_security = SessionSecurity(negotiate_flags,
                                                       session_key,
                                                       source="server")

        plaintext_data = b"\x50\x00\x6c\x00\x61\x00\x69\x00" \
                         b"\x6e\x00\x74\x00\x65\x00\x78\x00" \
                         b"\x74\x00"
        test_message, test_signature = \
            test_server_session_security.wrap(plaintext_data)

        expected_data = plaintext_data
        actual_data = test_session_security.unwrap(test_message,
                                                   test_signature)
        assert actual_data == expected_data
Example #12
0
class NtlmContext(object):

    def __init__(self, username, password, domain=None, workstation=None,
                 cbt_data=None, ntlm_compatibility=3):
        r"""
        Initialises a NTLM context to use when authenticating using the NTLM
        protocol.
        Initialises the NTLM context to use when sending and receiving messages
        to and from the server. You should be using this object as it supports
        NTLMv2 authenticate and it easier to use than before. It also brings in
        the ability to use signing and sealing with session_security and
        generate a MIC structure.

        :param username: The username to authenticate with
        :param password: The password for the username
        :param domain: The domain part of the username (None if n/a)
        :param workstation: The localworkstation (None if n/a)
        :param cbt_data: A GssChannelBindingsStruct or None to bind channel
            data with the auth process
        :param ntlm_compatibility: (Default 3)
            The Lan Manager Compatibility Level to use with the auth message
            This is set by an Administrator in the registry key
            'HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LmCompatibilityLevel'
            The values correspond to the following;
                0 : LM and NTLMv1
                1 : LM, NTLMv1 and NTLMv1 with Extended Session Security
                2 : NTLMv1 and NTLMv1 with Extended Session Security
                3-5 : NTLMv2 Only
            Note: Values 3 to 5 are no different from a client perspective
        """
        self.username = username
        self.password = password
        self.domain = domain
        self.workstation = workstation
        self.cbt_data = cbt_data
        self._server_certificate_hash = None  # deprecated for backwards compat
        self.ntlm_compatibility = ntlm_compatibility
        self.complete = False

        # Setting up our flags so the challenge message returns the target info
        # block if supported
        self.negotiate_flags = NegotiateFlags.NTLMSSP_NEGOTIATE_TARGET_INFO | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_128 | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_56 | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_UNICODE | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_VERSION | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_KEY_EXCH | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN | \
            NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL

        # Setting the message types based on the ntlm_compatibility level
        self._set_ntlm_compatibility_flags(self.ntlm_compatibility)

        self._negotiate_message = None
        self._challenge_message = None
        self._authenticate_message = None
        self._session_security = None

    @property
    def mic_present(self):
        if self._authenticate_message:
            return bool(self._authenticate_message.mic)

        return False

    @property
    def session_key(self):
        if self._authenticate_message:
            return self._authenticate_message.exported_session_key

    def reset_rc4_state(self, outgoing=True):
        """ Resets the signing cipher for the incoming or outgoing cipher. For SPNEGO for calculating mechListMIC. """
        if self._session_security:
            self._session_security.reset_rc4_state(outgoing=outgoing)

    def step(self, input_token=None):
        if self._negotiate_message is None:
            self._negotiate_message = NegotiateMessage(self.negotiate_flags,
                                                       self.domain,
                                                       self.workstation)
            return self._negotiate_message.get_data()
        else:
            self._challenge_message = ChallengeMessage(input_token)
            self._authenticate_message = AuthenticateMessage(
                self.username, self.password, self.domain, self.workstation,
                self._challenge_message, self.ntlm_compatibility,
                server_certificate_hash=self._server_certificate_hash,
                cbt_data=self.cbt_data
            )
            self._authenticate_message.add_mic(self._negotiate_message,
                                               self._challenge_message)

            flag_bytes = self._authenticate_message.negotiate_flags
            flags = struct.unpack("<I", flag_bytes)[0]
            if flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SEAL or \
                    flags & NegotiateFlags.NTLMSSP_NEGOTIATE_SIGN:
                self._session_security = SessionSecurity(
                    flags, self.session_key
                )

            self.complete = True
            return self._authenticate_message.get_data()

    def sign(self, data):
        return self._session_security.get_signature(data)

    def verify(self, data, signature):
        self._session_security.verify_signature(data, signature)

    def wrap(self, data):
        if self._session_security is None:
            raise NoAuthContextError("Cannot wrap data as no security context "
                                     "has been established")

        data, header = self._session_security.wrap(data)
        return header + data

    def unwrap(self, data):
        if self._session_security is None:
            raise NoAuthContextError("Cannot unwrap data as no security "
                                     "context has been established")
        header = data[0:16]
        data = data[16:]
        message = self._session_security.unwrap(data, header)
        return message

    def _set_ntlm_compatibility_flags(self, ntlm_compatibility):
        if (ntlm_compatibility >= 0) and (ntlm_compatibility <= 5):
            if ntlm_compatibility == 0:
                self.negotiate_flags |= \
                    NegotiateFlags.NTLMSSP_NEGOTIATE_NTLM | \
                    NegotiateFlags.NTLMSSP_NEGOTIATE_LM_KEY
            elif ntlm_compatibility == 1:
                self.negotiate_flags |= \
                    NegotiateFlags.NTLMSSP_NEGOTIATE_NTLM | \
                    NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
            else:
                self.negotiate_flags |= \
                    NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
        else:
            raise Exception("Unknown ntlm_compatibility level - "
                            "expecting value between 0 and 5")
Example #13
0
    def test_ntlm_context_with_mic(self, monkeypatch):
        monkeypatch.setattr('os.urandom', lambda s: b"\xaa" * 8)
        monkeypatch.setattr('ntlm_auth.messages.get_version',
                            lambda s: b"\x05\x01\x28\x0A\x00\x00\x00\x0F")
        monkeypatch.setattr('ntlm_auth.messages.get_random_export_session_key',
                            lambda: b"\x55" * 16)
        monkeypatch.setattr('ntlm_auth.compute_response.get_windows_timestamp',
                            lambda: b"\x00" * 8)

        ch = 'E3CA49271E5089CC48CE82109F1324F41DBEDDC29A777410C738F7868C4FF405'
        cbt_data = GssChannelBindingsStruct()
        cbt_data[cbt_data.APPLICATION_DATA] = b"tls-server-end-point:" + \
                                              base64.b16decode(ch)
        ntlm_context = NtlmContext("User",
                                   "Password",
                                   "Domain",
                                   "COMPUTER",
                                   cbt_data=cbt_data)
        ntlm_context.reset_rc4_state(
        )  # Verifies it won't fail when the session security isn't set up.

        actual_nego = ntlm_context.step()
        expected_nego = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
                        b"\x01\x00\x00\x00\x31\xb0\x88\xe2" \
                        b"\x06\x00\x06\x00\x28\x00\x00\x00" \
                        b"\x08\x00\x08\x00\x2e\x00\x00\x00" \
                        b"\x05\x01\x28\x0a\x00\x00\x00\x0f" \
                        b"\x44\x6f\x6d\x61\x69\x6e\x43\x4f" \
                        b"\x4d\x50\x55\x54\x45\x52"
        assert actual_nego == expected_nego
        assert not ntlm_context.mic_present
        assert not ntlm_context.complete

        challenge_msg = b"\x4E\x54\x4C\x4D\x53\x53\x50\x00" \
                        b"\x02\x00\x00\x00\x00\x00\x00\x00" \
                        b"\x38\x00\x00\x00\x33\x82\x8A\xE2" \
                        b"\x01\x23\x45\x67\x89\xAB\xCD\xEF" \
                        b"\x00\x00\x00\x00\x00\x00\x00\x00" \
                        b"\x30\x00\x30\x00\x38\x00\x00\x00" \
                        b"\x06\x01\xB1\x1D\x00\x00\x00\x0F" \
                        b"\x02\x00\x0C\x00\x44\x00\x6F\x00" \
                        b"\x6D\x00\x61\x00\x69\x00\x6E\x00" \
                        b"\x01\x00\x0C\x00\x53\x00\x65\x00" \
                        b"\x72\x00\x76\x00\x65\x00\x72\x00" \
                        b"\x07\x00\x08\x00\x00\x00\x00\x00" \
                        b"\x00\x00\x00\x00\x00\x00\x00\x00"
        actual_auth = ntlm_context.step(challenge_msg)
        expected_auth = b'\x4E\x54\x4C\x4D\x53\x53\x50\x00' \
                        b'\x03\x00\x00\x00\x18\x00\x18\x00' \
                        b'\x7C\x00\x00\x00\x7C\x00\x7C\x00' \
                        b'\x94\x00\x00\x00\x0C\x00\x0C\x00' \
                        b'\x58\x00\x00\x00\x08\x00\x08\x00' \
                        b'\x64\x00\x00\x00\x10\x00\x10\x00' \
                        b'\x6C\x00\x00\x00\x10\x00\x10\x00' \
                        b'\x10\x01\x00\x00\x31\x82\x8A\xE2' \
                        b'\x05\x01\x28\x0A\x00\x00\x00\x0F' \
                        b'\xC4\x45\x2C\xF7\xA8\x1E\x4D\x11' \
                        b'\xD0\x78\x18\x94\x09\x57\x5D\x9E' \
                        b'\x44\x00\x6F\x00\x6D\x00\x61\x00' \
                        b'\x69\x00\x6E\x00\x55\x00\x73\x00' \
                        b'\x65\x00\x72\x00\x43\x00\x4F\x00' \
                        b'\x4D\x00\x50\x00\x55\x00\x54\x00' \
                        b'\x45\x00\x52\x00\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\xA1\x3D\x03\x8A' \
                        b'\xD0\xCA\x02\x64\x33\x89\x7C\x33' \
                        b'\x5E\x0F\x56\xDF\x01\x01\x00\x00' \
                        b'\x00\x00\x00\x00\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\xAA\xAA\xAA\xAA' \
                        b'\xAA\xAA\xAA\xAA\x00\x00\x00\x00' \
                        b'\x02\x00\x0C\x00\x44\x00\x6F\x00' \
                        b'\x6D\x00\x61\x00\x69\x00\x6E\x00' \
                        b'\x01\x00\x0C\x00\x53\x00\x65\x00' \
                        b'\x72\x00\x76\x00\x65\x00\x72\x00' \
                        b'\x07\x00\x08\x00\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\x06\x00\x04\x00' \
                        b'\x02\x00\x00\x00\x0A\x00\x10\x00' \
                        b'\x6E\xA1\x9D\xF0\x66\xDA\x46\x22' \
                        b'\x05\x1F\x9C\x4F\x92\xC6\xDF\x74' \
                        b'\x00\x00\x00\x00\x00\x00\x00\x00' \
                        b'\x1D\x08\x89\xD1\xA5\xEE\xED\x21' \
                        b'\x91\x9E\x1A\xB8\x27\xC3\x0B\x17'

        assert actual_auth == expected_auth
        assert ntlm_context.complete
        assert ntlm_context.mic_present

        request_msg = b"test req"
        response_msg = b"test res"
        actual_wrapped = ntlm_context.wrap(request_msg)
        expected_wrapped = b"\x01\x00\x00\x00\xbc\xe3\x23\xa1" \
                           b"\x72\x06\x23\x78\x00\x00\x00\x00" \
                           b"\x70\x80\x1e\x11\xfe\x6b\x3a\xad"
        assert actual_wrapped == expected_wrapped

        server_sec = SessionSecurity(
            ntlm_context._session_security.negotiate_flags,
            ntlm_context._session_security.exported_session_key, "server")
        server_unwrap = server_sec.unwrap(actual_wrapped[16:],
                                          actual_wrapped[0:16])
        assert server_unwrap == request_msg

        response_wrapped = server_sec.wrap(response_msg)

        actual_unwrap = ntlm_context.unwrap(response_wrapped[1] +
                                            response_wrapped[0])
        assert actual_unwrap == response_msg

        msg = b"Hello"
        actual_sig1 = ntlm_context.sign(msg)
        expected_sig1 = b"\x01\x00\x00\x00\x08\xF0\x0D\x86\x34\x05\x1A\x1D\x01\x00\x00\x00"
        assert actual_sig1 == expected_sig1
        server_sec.verify_signature(msg, actual_sig1)

        actual_sig2 = ntlm_context.sign(msg)
        expected_sig2 = b"\x01\x00\x00\x00\x07\x64\x0C\x30\x1C\xD7\x76\xF0\x02\x00\x00\x00"
        assert actual_sig2 == expected_sig2
        server_sec.verify_signature(msg, actual_sig2)

        ntlm_context.reset_rc4_state()
        actual_sig3 = ntlm_context.sign(msg)
        expected_sig3 = b"\x01\x00\x00\x00\x1E\xD4\xA3\xE5\xE8\x05\x74\x01\x03\x00\x00\x00"
        assert actual_sig3 == expected_sig3

        server_sec.reset_rc4_state(outgoing=False)
        server_sec.verify_signature(msg, actual_sig3)

        server_sig = server_sec.get_signature(msg)
        ntlm_context.verify(msg, server_sig)
Example #14
0
    def test_ntlm_context(self, monkeypatch):
        monkeypatch.setattr('os.urandom', lambda s: b"\xaa" * 8)
        monkeypatch.setattr('ntlm_auth.messages.get_version',
                            lambda s: b"\x05\x01\x28\x0A\x00\x00\x00\x0F")
        monkeypatch.setattr('ntlm_auth.messages.get_random_export_session_key',
                            lambda: b"\x55" * 16)
        monkeypatch.setattr('ntlm_auth.compute_response.get_windows_timestamp',
                            lambda: b"\x00" * 8)

        ch = 'E3CA49271E5089CC48CE82109F1324F41DBEDDC29A777410C738F7868C4FF405'
        cbt_data = GssChannelBindingsStruct()
        cbt_data[cbt_data.APPLICATION_DATA] = b"tls-server-end-point:" + \
                                              base64.b16decode(ch)
        ntlm_context = NtlmContext("User",
                                   "Password",
                                   "Domain",
                                   "COMPUTER",
                                   cbt_data=cbt_data)
        actual_nego = ntlm_context.step()
        expected_nego = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
                        b"\x01\x00\x00\x00\x31\xb0\x88\xe2" \
                        b"\x06\x00\x06\x00\x28\x00\x00\x00" \
                        b"\x08\x00\x08\x00\x2e\x00\x00\x00" \
                        b"\x05\x01\x28\x0a\x00\x00\x00\x0f" \
                        b"\x44\x6f\x6d\x61\x69\x6e\x43\x4f" \
                        b"\x4d\x50\x55\x54\x45\x52"
        assert actual_nego == expected_nego
        assert not ntlm_context.mic_present
        assert not ntlm_context.complete

        challenge_msg = b"\x4e\x54\x4c\x4d\x53\x53\x50\x00" \
                        b"\x02\x00\x00\x00\x2f\x82\x88\xe2" \
                        b"\x38\x00\x00\x00\x33\x82\x8a\xe2" \
                        b"\x01\x23\x45\x67\x89\xab\xcd\xef" \
                        b"\x00\x00\x00\x00\x00\x00\x00\x00" \
                        b"\x24\x00\x24\x00\x44\x00\x00\x00" \
                        b"\x06\x00\x70\x17\x00\x00\x00\x0f" \
                        b"\x53\x00\x65\x00\x72\x00\x76\x00" \
                        b"\x65\x00\x72\x00\x02\x00\x0c\x00" \
                        b"\x44\x00\x6f\x00\x6d\x00\x61\x00" \
                        b"\x69\x00\x6e\x00\x01\x00\x0c\x00" \
                        b"\x53\x00\x65\x00\x72\x00\x76\x00" \
                        b"\x65\x00\x72\x00\x00\x00\x00\x00"
        actual_auth = ntlm_context.step(challenge_msg)
        expected_auth = b'\x4e\x54\x4c\x4d\x53\x53\x50\x00' \
                        b'\x03\x00\x00\x00\x18\x00\x18\x00' \
                        b'\x6c\x00\x00\x00\x68\x00\x68\x00' \
                        b'\x84\x00\x00\x00\x0c\x00\x0c\x00' \
                        b'\x48\x00\x00\x00\x08\x00\x08\x00' \
                        b'\x54\x00\x00\x00\x10\x00\x10\x00' \
                        b'\x5c\x00\x00\x00\x10\x00\x10\x00' \
                        b'\xec\x00\x00\x00\x31\x82\x8a\xe2' \
                        b'\x05\x01\x28\x0a\x00\x00\x00\x0f' \
                        b'\x44\x00\x6f\x00\x6d\x00\x61\x00' \
                        b'\x69\x00\x6e\x00\x55\x00\x73\x00' \
                        b'\x65\x00\x72\x00\x43\x00\x4f\x00' \
                        b'\x4d\x00\x50\x00\x55\x00\x54\x00' \
                        b'\x45\x00\x52\x00\x86\xc3\x50\x97' \
                        b'\xac\x9c\xec\x10\x25\x54\x76\x4a' \
                        b'\x57\xcc\xcc\x19\xaa\xaa\xaa\xaa' \
                        b'\xaa\xaa\xaa\xaa\x04\x10\xc4\x7a' \
                        b'\xcf\x19\x97\x89\xde\x7f\x20\x11' \
                        b'\x95\x7a\xea\x50\x01\x01\x00\x00' \
                        b'\x00\x00\x00\x00\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\xaa\xaa\xaa\xaa' \
                        b'\xaa\xaa\xaa\xaa\x00\x00\x00\x00' \
                        b'\x02\x00\x0c\x00\x44\x00\x6f\x00' \
                        b'\x6d\x00\x61\x00\x69\x00\x6e\x00' \
                        b'\x01\x00\x0c\x00\x53\x00\x65\x00' \
                        b'\x72\x00\x76\x00\x65\x00\x72\x00' \
                        b'\x0a\x00\x10\x00\x6e\xa1\x9d\xf0' \
                        b'\x66\xda\x46\x22\x05\x1f\x9c\x4f' \
                        b'\x92\xc6\xdf\x74\x00\x00\x00\x00' \
                        b'\x00\x00\x00\x00\xe5\x69\x95\x1d' \
                        b'\x15\xd4\x73\x5f\x49\xe1\x4c\xf9' \
                        b'\xa7\xd3\xe6\x72'

        assert actual_auth == expected_auth
        assert ntlm_context.complete
        assert not ntlm_context.mic_present

        request_msg = b"test req"
        response_msg = b"test res"
        actual_wrapped = ntlm_context.wrap(request_msg)
        expected_wrapped = b"\x01\x00\x00\x00\xbc\xe3\x23\xa1" \
                           b"\x72\x06\x23\x78\x00\x00\x00\x00" \
                           b"\x70\x80\x1e\x11\xfe\x6b\x3a\xad"
        assert actual_wrapped == expected_wrapped

        server_sec = SessionSecurity(
            ntlm_context._session_security.negotiate_flags,
            ntlm_context._session_security.exported_session_key, "server")
        server_unwrap = server_sec.unwrap(actual_wrapped[16:],
                                          actual_wrapped[0:16])
        assert server_unwrap == request_msg

        response_wrapped = server_sec.wrap(response_msg)

        actual_unwrap = ntlm_context.unwrap(response_wrapped[1] +
                                            response_wrapped[0])
        assert actual_unwrap == response_msg