def test_invalid_protocol(): expected = "Invalid protocol specified 'fake', must be kerberos, negotiate, or ntlm" with pytest.raises(ValueError, match=expected): spnego.client(None, None, protocol='fake') with pytest.raises(ValueError, match=expected): spnego.server(protocol='fake')
def test_negotiate_with_raw_ntlm(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_negotiate) negotiate = c.step() assert negotiate.startswith(b"NTLMSSP\x00\x01") assert not c.complete assert not s.complete challenge = s.step(negotiate) assert challenge.startswith(b"NTLMSSP\x00\x02") assert not c.complete assert not s.complete authenticate = c.step(challenge) assert authenticate.startswith(b"NTLMSSP\x00\x03") assert c.complete assert not s.complete final = s.step(authenticate) assert final is None assert c.complete assert s.complete _message_test(c, s)
def test_negotiate_with_kerberos(kerb_cred): c = spnego.client(kerb_cred.user_princ, None, hostname=socket.getfqdn(), options=spnego.NegotiateOptions.use_negotiate) s = spnego.server(options=spnego.NegotiateOptions.use_negotiate) token1 = c.step() assert isinstance(token1, bytes) token2 = s.step(token1) assert isinstance(token2, bytes) token3 = c.step(token2) assert token3 is None # Make sure it reports the right protocol assert c.negotiated_protocol == 'kerberos' assert s.negotiated_protocol == 'kerberos' assert isinstance(c.session_key, bytes) assert isinstance(s.session_key, bytes) assert c.session_key == s.session_key assert c.client_principal is None assert s.client_principal == kerb_cred.user_princ assert c.context_attr & spnego.ContextReq.mutual_auth assert s.context_attr & spnego.ContextReq.mutual_auth _message_test(c, s)
def main(): server = socket.gethostname() username = '******' password = '******' c = spnego.client(username, password, server) s = spnego.server(server) in_token = None while not c.complete: out_token = c.step(in_token) if not out_token: break in_token = s.step(out_token) print("Client Session key: %s" % base64.b64encode(c.session_key).decode('utf-8')) print("Server Session key: %s" % base64.b64encode(s.session_key).decode('utf-8')) print("Authenticated client: %s" % s.client_principal) c_enc_msg = c.wrap(b"Hello World") s_dec_msg = s.unwrap(c_enc_msg.data) s_enc_msg = s.wrap(s_dec_msg.data) c_dec_msg = c.unwrap(s_enc_msg.data) c_sig = c.sign(b"data") s.verify(b"data", c_sig) s_sig = s.sign(b"data") c.verify(b"data", s_sig)
def main(): client = spnego.client('username', 'password', hostname='server') in_token = None while client.complete: out_token = client.step(in_token) if not out_token: break in_token = exchange_data(out_token) print("Negotiated protocol: %s" % client.negotiated_protocol) buffer = [ spnego.iov.BufferType.header, b"my secret", spnego.iov.BufferType.padding, ] enc_result = client.wrap_iov(buffer) header = enc_result.buffers[0].data enc_data = enc_result.buffers[1].data + enc_result.buffers[2].data or b"" resp = exchange_data(struct.pack("<I", len(header)) + header + enc_data) header_len = struct.unpack("<I", resp[:4])[0] header = resp[4:4 + header_len] enc_data = resp[4 + header_len:] buffer = [ spnego.iov.IOVBuffer(spnego.iov.BufferType.header, header), enc_data, ] dec_result = client.unwrap_iov(buffer) print("Server response: %s" % dec_result.buffers[1].data.decode('utf-8'))
def test_sspi_ntlm_auth_no_sign_or_seal(client_opt, server_opt, ntlm_cred): if client_opt & spnego.NegotiateOptions.use_gssapi or server_opt & spnego.NegotiateOptions.use_gssapi: if 'ntlm' not in spnego.gss.GSSAPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through GSSAPI') elif client_opt & spnego.NegotiateOptions.use_sspi or server_opt & spnego.NegotiateOptions.use_sspi: if 'ntlm' not in spnego.sspi.SSPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through SSPI') # Build the initial context and assert the defaults. c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=client_opt, protocol='ntlm', context_req=0) s = spnego.server(options=server_opt, protocol='ntlm', context_req=0) _ntlm_test(c, s) assert c.client_principal is None assert s.client_principal == ntlm_cred[0] # Client sign, server verify plaintext = os.urandom(3) c_sig = c.sign(plaintext) s.verify(plaintext, c_sig) # Server sign, client verify plaintext = os.urandom(9) s_sig = s.sign(plaintext) c.verify(plaintext, s_sig)
def test_token_no_common_mechs(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], options=spnego.NegotiateOptions.use_negotiate) with pytest.raises(BadMechanismError, match="Unable to negotiate common mechanism"): c.step(NegTokenInit(mech_types=["1.2.3.4"]).pack())
def test_token_rejected(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], options=spnego.NegotiateOptions.use_negotiate) c.step() token_resp = NegTokenResp(neg_state=NegState.reject).pack() with pytest.raises( InvalidTokenError, match="Received SPNEGO rejection with no token error message"): c.step(token_resp)
def generate_request_header(self, response, host, is_preemptive=False): """ Generates the GSSAPI authentication token with kerberos. If any GSSAPI step fails, raise KerberosExchangeError with failure detail. """ # Flags used by kerberos module. gssflags = spnego.ContextReq.sequence_detect if self.delegate: gssflags |= spnego.ContextReq.delegate if self.mutual_authentication != DISABLED: gssflags |= spnego.ContextReq.mutual_auth try: kerb_stage = "ctx init" # contexts still need to be stored by host, but hostname_override # allows use of an arbitrary hostname for the kerberos exchange # (eg, in cases of aliased hosts, internal vs external, CNAMEs # w/ name-based HTTP hosting) kerb_host = self.hostname_override if self.hostname_override is not None else host self._context[host] = ctx = spnego.client( username=self.principal, hostname=kerb_host, service=self.service, channel_bindings=self.cbt_struct, context_req=gssflags, protocol="kerberos", ) # if we have a previous response from the server, use it to continue # the auth process, otherwise use an empty value negotiate_resp_value = None if is_preemptive else _negotiate_value( response) kerb_stage = "ctx step" gss_response = ctx.step(in_token=negotiate_resp_value) return "Negotiate {0}".format( base64.b64encode(gss_response).decode()) except spnego.exceptions.SpnegoError as error: log.exception( "generate_request_header(): {0} failed:".format(kerb_stage)) log.exception(error) raise KerberosExchangeError("%s failed: %s" % (kerb_stage, str(error))) from error
def test_ntlm_bad_mic(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = memoryview(bytearray(c.step(s.step(c.step())))) auth[64:80] = b"\x01" * 16 with pytest.raises(InvalidTokenError, match="Invalid MIC in NTLM authentication message"): s.step(auth.tobytes())
def test_ntlm_anon_response(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = Authenticate.unpack(c.step(s.step(c.step()))) anon_auth = Authenticate(flags=auth.flags, lm_challenge_response=b"\x00", nt_challenge_response=b"").pack() with pytest.raises(OperationNotAvailableError, match="Anonymous user authentication not implemented"): s.step(anon_auth)
def test_sspi_ntlm_lm_compat(lm_compat_level, ntlm_cred, monkeypatch): monkeypatch.setenv('LM_COMPAT_LEVEL', str(lm_compat_level)) c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), protocol='ntlm', options=spnego.NegotiateOptions.use_ntlm) s = spnego.server(options=spnego.NegotiateOptions.use_sspi, protocol='ntlm') _ntlm_test(c, s) assert c.client_principal is None assert s.client_principal == ntlm_cred[0] _message_test(c, s)
def test_ntlm_lm_request(ntlm_cred, monkeypatch): monkeypatch.setenv('LM_COMPAT_LEVEL', '0') c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = memoryview(bytearray(c.step(s.step(c.step())))) auth[20:28] = b"\x00" * 8 s.step(auth.tobytes()) assert c.complete assert s.complete
def test_ntlm_auth(lm_compat_level, ntlm_cred, monkeypatch): if lm_compat_level is not None: monkeypatch.setenv('LM_COMPAT_LEVEL', str(lm_compat_level)) # Build the initial context and assert the defaults. c = spnego.client(ntlm_cred[0], ntlm_cred[1], protocol='ntlm', options=spnego.NegotiateOptions.use_ntlm) s = spnego.server(protocol='ntlm', options=spnego.NegotiateOptions.use_ntlm) _ntlm_test(c, s) assert c.client_principal is None assert s.client_principal == ntlm_cred[0] _message_test(c, s)
def test_ntlm_nt_v1_request(ntlm_cred, monkeypatch): monkeypatch.setenv('LM_COMPAT_LEVEL', '0') c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') monkeypatch.setenv('LM_COMPAT_LEVEL', '4') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = c.step(s.step(c.step())) s.step(auth) assert c.complete assert s.complete
def test_ntlm_no_nt_v1_allowed(ntlm_cred, monkeypatch): monkeypatch.setenv('LM_COMPAT_LEVEL', '0') c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') monkeypatch.setenv('LM_COMPAT_LEVEL', '5') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = c.step(s.step(c.step())) with pytest.raises( InvalidTokenError, match="Acceptor settings are set to reject NTv1 responses"): s.step(auth)
def test_ntlm_no_key_exch(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') c._context_req &= ~0x40000000 # NTLMSSP_NEGOTIATE_KEY_EXCH auth = c.step(s.step(c.step())) s.step(auth) # Make sure EncryptedRandomSessionKeyFields was set to 0 (no KEY_EXCH). assert auth[52:54] == b"\x00\x00" plaintext = os.urandom(32) c_wrap_result = c.wrap(plaintext) assert c_wrap_result.encrypted assert c_wrap_result.data != plaintext s_unwrap_result = s.unwrap(c_wrap_result.data) assert s_unwrap_result.data == plaintext assert s_unwrap_result.encrypted plaintext = os.urandom(17) s_wrap_result = s.wrap(plaintext) assert s_wrap_result.encrypted assert s_wrap_result.data != plaintext c_unwrap_result = c.unwrap(s_wrap_result.data) assert c_unwrap_result.data == plaintext assert c_unwrap_result.encrypted plaintext = os.urandom(3) c_sig = c.sign(plaintext) s.verify(plaintext, c_sig) plaintext = os.urandom(9) s_sig = s.sign(plaintext) c.verify(plaintext, s_sig)
def test_gssapi_ntlm_lm_compat(lm_compat_level, ntlm_cred, monkeypatch): monkeypatch.setenv('LM_COMPAT_LEVEL', str(lm_compat_level)) c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), protocol='ntlm', options=spnego.NegotiateOptions.use_ntlm) s = spnego.server(options=spnego.NegotiateOptions.use_gssapi, protocol='ntlm') # gss-ntlmssp version on CI may be too old to test the session key test_session_key = 'ntlm' in spnego.gss.GSSAPIProxy.available_protocols( spnego.NegotiateOptions.session_key) _ntlm_test(c, s, test_session_key=test_session_key) assert c.client_principal is None assert s.client_principal == ntlm_cred[0] _message_test(c, s)
def test_gssapi_kerberos_auth(kerb_cred): c = spnego.client(kerb_cred.user_princ, None, hostname=socket.getfqdn(), protocol='kerberos', options=spnego.NegotiateOptions.use_gssapi) s = spnego.server(options=spnego.NegotiateOptions.use_gssapi, protocol='kerberos') assert not c.complete assert not s.complete assert s.negotiated_protocol is None with pytest.raises(SpnegoError, match="Retrieving session key"): _ = c.session_key with pytest.raises(SpnegoError, match="Retrieving session key"): _ = s.session_key token1 = c.step() assert isinstance(token1, bytes) assert not c.complete assert not s.complete assert s.negotiated_protocol is None token2 = s.step(token1) assert isinstance(token2, bytes) assert not c.complete assert s.complete assert s.negotiated_protocol == 'kerberos' token3 = c.step(token2) assert token3 is None assert c.complete assert s.complete assert isinstance(c.session_key, bytes) assert isinstance(s.session_key, bytes) assert c.session_key == s.session_key assert c.client_principal is None assert s.client_principal == kerb_cred.user_princ _message_test(c, s)
def test_ntlm_no_lm_allowed(ntlm_cred, monkeypatch): monkeypatch.setenv('LM_COMPAT_LEVEL', '0') c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') monkeypatch.setenv('LM_COMPAT_LEVEL', '4') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = memoryview(bytearray(c.step(s.step(c.step())))) auth[20:28] = b"\x00" * 8 with pytest.raises( InvalidTokenError, match="Acceptor settings are set to reject LM responses"): s.step(auth)
def test_token_acceptor_first(ntlm_cred): c = spnego.client(ntlm_cred[0], ntlm_cred[1], options=spnego.NegotiateOptions.use_negotiate) s = spnego.server(options=spnego.NegotiateOptions.use_negotiate) assert c._mech_list == [] assert s._mech_list == [] token1 = s.step() assert isinstance(token1, bytes) assert not c.complete assert not s.complete assert c._mech_list == [] assert s._mech_list == [GSSMech.ntlm.value] negotiate = c.step(token1) assert isinstance(negotiate, bytes) assert not c.complete assert not s.complete assert c._mech_list == [GSSMech.ntlm.value] assert s._mech_list == [GSSMech.ntlm.value] challenge = s.step(negotiate) assert isinstance(challenge, bytes) assert not c.complete assert not s.complete authenticate = c.step(challenge) assert isinstance(authenticate, bytes) assert not c.complete assert not s.complete mech_list_mic = s.step(authenticate) assert isinstance(mech_list_mic, bytes) assert not c.complete assert s.complete final_token = c.step(mech_list_mic) assert final_token is None assert c.complete assert s.complete
def main(): client = spnego.client('username', 'password', hostname='server') in_token = None while client.complete: out_token = client.step(in_token) if not out_token: break in_token = exchange_data(out_token) print("Negotiated protocol: %s" % client.negotiated_protocol) data = b"my secret" enc_data = client.wrap(data) resp = exchange_data(enc_data.data) dec_data = client.unwrap(resp) print("Server response: %s" % dec_data.data.decode('utf-8'))
def test_ntlm_invalid_password(client_opt, ntlm_cred): if client_opt & spnego.NegotiateOptions.use_gssapi: if 'ntlm' not in spnego.gss.GSSAPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through GSSAPI') elif client_opt & spnego.NegotiateOptions.use_sspi: if 'ntlm' not in spnego.sspi.SSPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through SSPI') c = spnego.client(ntlm_cred[0], u"Invalid", hostname=socket.gethostname(), options=client_opt, protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') auth = c.step(s.step(c.step())) with pytest.raises(InvalidTokenError, match="Invalid NTLM response from initiator"): s.step(auth)
def test_gssapi_ntlm_auth(client_opt, server_opt, ntlm_cred, cbt): # Build the initial context and assert the defaults. kwargs = { 'protocol': 'ntlm', } if cbt: kwargs[ 'channel_bindings'] = spnego.channel_bindings.GssChannelBindings( application_data=b'test_data:\x00\x01') c = spnego.client(ntlm_cred[0], ntlm_cred[1], options=client_opt, **kwargs) s = spnego.server(options=server_opt, **kwargs) # gss-ntlmssp version on CI may be too old to test the session key test_session_key = 'ntlm' in spnego.gss.GSSAPIProxy.available_protocols( spnego.NegotiateOptions.session_key) _ntlm_test(c, s, test_session_key=test_session_key) assert c.client_principal is None assert s.client_principal == ntlm_cred[0] _message_test(c, s)
def test_sspi_ntlm_auth(client_opt, server_opt, cbt, ntlm_cred): # Build the initial context and assert the defaults. kwargs = { 'protocol': 'ntlm', } if cbt: kwargs[ 'channel_bindings'] = spnego.channel_bindings.GssChannelBindings( application_data=b'test_data:\x00\x01') c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=client_opt, **kwargs) s = spnego.server(options=server_opt, **kwargs) _ntlm_test(c, s) assert c.client_principal is None assert s.client_principal == ntlm_cred[0] _message_test(c, s)
def test_ntlm_bad_bindings(client_opt, present, ntlm_cred): if client_opt & spnego.NegotiateOptions.use_gssapi: if 'ntlm' not in spnego.gss.GSSAPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through GSSAPI') elif client_opt & spnego.NegotiateOptions.use_sspi: if 'ntlm' not in spnego.sspi.SSPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through SSPI') initiator_cbt = None if present: initiator_cbt = spnego.channel_bindings.GssChannelBindings( application_data=b"tls-host-data:bad") c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=client_opt, protocol='ntlm', channel_bindings=initiator_cbt) acceptor_cbt = spnego.channel_bindings.GssChannelBindings( application_data=b"tls-host-data:test") s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm', channel_bindings=acceptor_cbt) auth = c.step(s.step(c.step())) if present: expected = "Acceptor bindings do not match initiator bindings" else: expected = "Acceptor bindings specified but not present in initiator response" with pytest.raises(BadBindingsError, match=expected): s.step(auth)
def test_ntlm_custom_time(include_time, expected, ntlm_cred, mocker, monkeypatch): c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') b_negotiate = c.step() negotiate = Negotiate.unpack(b_negotiate) flags = negotiate.flags | NegotiateFlags.request_target | NegotiateFlags.ntlm | \ NegotiateFlags.always_sign | NegotiateFlags.target_info | NegotiateFlags.target_type_server server_challenge = os.urandom(8) target_name = to_text(socket.gethostname()).upper() target_info = TargetInfo() target_info[AvId.nb_computer_name] = target_name target_info[AvId.nb_domain_name] = u"WORKSTATION" target_info[AvId.dns_computer_name] = to_text(socket.getfqdn()) if include_time: target_info[AvId.timestamp] = FileTime.now() challenge = Challenge(flags, server_challenge, target_name=target_name, target_info=target_info) mock_now = mocker.MagicMock() mock_now.side_effect = FileTime.now monkeypatch.setattr(FileTime, 'now', mock_now) c.step(challenge.pack()) assert c.complete assert mock_now.call_count == expected
def test_ntlm_verify_fail(client_opt, ntlm_cred): if client_opt & spnego.NegotiateOptions.use_gssapi: if 'ntlm' not in spnego.gss.GSSAPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through GSSAPI') elif client_opt & spnego.NegotiateOptions.use_sspi: if 'ntlm' not in spnego.sspi.SSPIProxy.available_protocols(): pytest.skip('Test requires NTLM to be available through SSPI') c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=client_opt, protocol='ntlm') s = spnego.server(options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') s.step(c.step(s.step(c.step()))) c.sign(b"data") sig = c.sign(b"data 2") with pytest.raises(BadMICError, match="Invalid Message integrity Check"): s.verify(b"data", sig)
def test_ntlm_workstation_override(env_var, expected, ntlm_cred, monkeypatch): if env_var is not None: monkeypatch.setenv('NETBIOS_COMPUTER_NAME', env_var) c = spnego.client(ntlm_cred[0], ntlm_cred[1], hostname=socket.gethostname(), options=spnego.NegotiateOptions.use_ntlm, protocol='ntlm') b_negotiate = c.step() negotiate = Negotiate.unpack(b_negotiate) flags = negotiate.flags | NegotiateFlags.request_target | NegotiateFlags.ntlm | \ NegotiateFlags.always_sign | NegotiateFlags.target_info | NegotiateFlags.target_type_server server_challenge = os.urandom(8) target_name = to_text(socket.gethostname()).upper() target_info = TargetInfo() target_info[AvId.nb_computer_name] = target_name target_info[AvId.nb_domain_name] = u"WORKSTATION" target_info[AvId.dns_computer_name] = to_text(socket.getfqdn()) target_info[AvId.timestamp] = FileTime.now() version = Version(10, 0, 0, 1) challenge = Challenge(flags, server_challenge, target_name=target_name, target_info=target_info, version=version) b_auth = c.step(challenge.pack()) auth = Authenticate.unpack(b_auth) assert auth.workstation == expected
def handle_401(self, response, **kwargs): response_auth_header = kwargs.pop('_pypsrp_auth_provider') response_auth_header_l = response_auth_header.lower() auth_provider = self.auth_provider if response_auth_header_l != self.auth_provider: if self.auth_provider == 'negotiate': auth_provider = response_auth_header_l elif response_auth_header_l != 'negotiate': raise ValueError( "Server responded with the auth protocol '%s' which is incompatible with the " "specified auth_provider '%s'" % (response_auth_header, auth_provider)) host = get_hostname(response.url) auth_hostname = self.hostname_override or host cbt = None if self.send_cbt: cbt_app_data = HTTPNegotiateAuth._get_cbt_data(response) if cbt_app_data: cbt = spnego.channel_bindings.GssChannelBindings( application_data=cbt_app_data) context_req = spnego.ContextReq.default if self.delegate: context_req |= spnego.ContextReq.delegate spnego_options = spnego.NegotiateOptions.wrapping_winrm if self.wrap_required else 0 context = spnego.client(self.username, self.password, hostname=auth_hostname, service=self.service, channel_bindings=cbt, context_req=context_req, protocol=auth_provider, options=spnego_options) self.contexts[host] = context out_token = context.step() while not context.complete or out_token is not None: # consume content and release the original connection to allow the # new request to reuse the same one. response.content response.raw.release_conn() # create a request with the Negotiate token present request = response.request.copy() log.debug("Sending http request with new auth token") self._set_auth_token(request, out_token, response_auth_header) # send the request with the auth token and get the response response = response.connection.send(request, **kwargs) # attempt to retrieve the auth token response in_token = self._get_auth_token(response, self._regex) # break if there was no token received from the host and return the # last response if in_token in [None, b""]: log.debug( "Did not receive a http response with an auth response, stopping authentication process" ) break out_token = context.step(in_token) # This is used by the message encryption to decide the MIME protocol. setattr(context, 'response_auth_header', response_auth_header_l) return response