From 0256cec6f74372ca2153a5560c9dfe42f174061d Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Fri, 7 Jun 2024 09:18:03 +1000 Subject: [PATCH] Favour pure NTLM provider and fix SPN (#137) Provides actual values for the SPN target name on the NTLM payloads. Also favours the pure NTLM provider in the spnego library if a username and password are provided. This is done for backwards compatibility with older releases of this library which didn't use SSPI. --- requests_ntlm/requests_ntlm.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/requests_ntlm/requests_ntlm.py b/requests_ntlm/requests_ntlm.py index 7361b57..1666e10 100644 --- a/requests_ntlm/requests_ntlm.py +++ b/requests_ntlm/requests_ntlm.py @@ -2,6 +2,8 @@ import base64 import typing as t +from urllib.parse import urlparse + from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes @@ -94,11 +96,25 @@ def retry_using_http_NTLM_auth( response.raw.release_conn() request = response.request.copy() + target_hostname = urlparse(response.url).hostname + spnego_options = spnego.NegotiateOptions.none + if self.username and self.password: + # If a username and password are specified force spnego to use the + # pure NTLM code. This is for backwards compatibility with older + # requests-ntlm versions which never used SSPI. If no username and + # password are specified we need to rely on the cached SSPI + # behaviour. + # https://github.com/requests/requests-ntlm/issues/136#issuecomment-1751677055 + spnego_options = spnego.NegotiateOptions.use_ntlm + client = spnego.client( self.username, self.password, protocol="ntlm", channel_bindings=cbt, + hostname=target_hostname, + service="http", + options=spnego_options, ) # Perform the first step of the NTLM authentication negotiate_message = base64.b64encode(client.step()).decode()