NTLM authentication in Python
Solution 1
import win32com.client
url = 'https://....'
h = win32com.client.Dispatch('WinHTTP.WinHTTPRequest.5.1')
h.SetAutoLogonPolicy(0)
h.Open('GET', url, False)
h.Send()
result = h.responseText
result
Solution 2
I've found out what was wrong. I should keeping the connection alive. That's the goods! Now this problem is solved.
class WindoewNtlmMessageGenerator:
def __init__(self,user=None):
import win32api,sspi
if not user:
user = win32api.GetUserName()
self.sspi_client = sspi.ClientAuth("NTLM",user)
def create_auth_req(self):
import pywintypes
output_buffer = None
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(None)
except pywintypes.error:
return None
auth_req = output_buffer[0].Buffer
auth_req = base64.b64encode(auth_req)
return auth_req
def create_challenge_response(self,challenge):
import pywintypes
output_buffer = None
input_buffer = challenge
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(input_buffer)
except pywintypes.error:
return None
response_msg = output_buffer[0].Buffer
response_msg = base64.b64encode(response_msg)
return response_msg
SHOD='qqq.yyy.dev'
answer='result.xml'
fname='request.xml'
try:
a_file = open(fname, 'r')
f=open(fname, 'r')
except IOError:
sys.exit()
size = os.path.getsize(fname)
i=0
for line in f:
i=i+1
count_string=i
f.close()
size=size-count_string+1
print '1'
try:
webservice = httplib.HTTPConnection(SHOD)
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Content-length", "%d" % 0)
webservice.putheader("Content-type", "text/xml")
#webservice.putheader("User-Agent", 'Python-urllib/2.6')
webservice.endheaders()
res=webservice.getresponse()
except:
msg= "unable to connect to URL: "+ SHOD
sys.exit()
if res.status == 401:
auth_methods = [s.strip() for s in
res.msg.get('WWW-Authenticate').split(",")]
print auth_methods
if res.status <> 401:
msg= "unable to connect to URL: "+ SHOD_
log_error(msg,answer)
sys.exit()
print '2'
ntlm_gen = WindoewNtlmMessageGenerator()
auth_req_msg = ntlm_gen.create_auth_req()
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Content-length", "%d" % 0)
webservice.putheader("Connection", "Keep-Alive")
#webservice.putheader("User-Agent", 'Python-urllib/2.6')
webservice.putheader('Authorization', 'NTLM'+' '+auth_req_msg)
webservice.endheaders()
resp = webservice.getresponse()
resp.read()
print resp.status
challenge = resp.msg.get('WWW-Authenticate')
challenge_dec = base64.b64decode(challenge.split()[1])
print '3'
msg3 = ntlm_gen.create_challenge_response(challenge_dec)
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Content-type", "text/xml; charset=UTF-8")
webservice.putheader("Content-length", "%d" %(size))
webservice.putheader("Connection", "Close")
webservice.putheader('Authorization', 'NTLM'+' '+msg3)
#webservice.putheader("User-Agent", 'Python-urllib/2.6')
webservice.endheaders()
sable = a_file.read()
webservice.send(sable)
resp = webservice.getresponse()
res=resp.read()
Admin
Updated on July 27, 2022Comments
-
Admin almost 2 years
I'm trying to implement NTLM authentication on IIS (Windows Server 2003) from Windows 7 with python. LAN Manager Authentication Level: Send NTLM response only.
Client machine and server are in the same domain.
Domain controller (AD) is on another server (also running Windows Server 2003).I receive 401.1 - Unauthorized: Access is denied due to invalid credentials. Could you please help me find out what is wrong with this code and/or show me the other possible directions to solve this problem (using NTLM or Kerberos)?
import sys, httplib, base64, string import urllib2 import win32api import sspi import pywintypes import socket class WindoewNtlmMessageGenerator: def __init__(self,user=None): import win32api,sspi if not user: user = win32api.GetUserName() self.sspi_client = sspi.ClientAuth("NTLM",user) def create_auth_req(self): import pywintypes output_buffer = None error_msg = None try: error_msg, output_buffer = self.sspi_client.authorize(None) except pywintypes.error: return None auth_req = output_buffer[0].Buffer auth_req = base64.encodestring(auth_req) auth_req = string.replace(auth_req,'\012','') return auth_req def create_challenge_response(self,challenge): import pywintypes output_buffer = None input_buffer = challenge error_msg = None try: error_msg, output_buffer = self.sspi_client.authorize(input_buffer) except pywintypes.error: return None response_msg = output_buffer[0].Buffer response_msg = base64.encodestring(response_msg) response_msg = string.replace(response_msg,'\012','') return response_msg fname='request.xml' request = file(fname).read() ip_host = '10.0.3.112' ntlm_gen = WindoewNtlmMessageGenerator() auth_req_msg = ntlm_gen.create_auth_req() auth_req_msg_dec = base64.decodestring(auth_req_msg) auth_req_msg = string.replace(auth_req_msg,'\012','') webservice = httplib.HTTPConnection(ip_host) webservice.putrequest("POST", "/idc/idcplg") webservice.putheader("Content-length", "%d" % len(request)) webservice.putheader('Authorization', 'NTLM'+' '+auth_req_msg) webservice.endheaders() resp = webservice.getresponse() resp.read() challenge = resp.msg.get('WWW-Authenticate') challenge_dec = base64.decodestring(challenge.split()[1]) msg3 = ntlm_gen.create_challenge_response(challenge_dec) webservice = httplib.HTTP(ip_host) webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet") webservice.putheader("Host", SHOD) webservice.putheader("Content-length", "%d" % len(request)) webservice.putheader('Authorization', 'NTLM'+' '+msg3) webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"") webservice.putheader("SOAPAction", "\"\"") webservice.endheaders() webservice.send(request) statuscode, statusmessage, header = webservice.getreply() res = webservice.getfile().read() res_file = file('result.txt','wb') res_file.write(res) res_file.close()
sspi.py is available here: https://ironpython.svn.codeplex.com/svn/IronPython_Main/External.LCA_RESTRICTED/Languages/IronPython/27/Lib/site-packages/win32/lib/sspi.py
Thanks!
-
Bill the Lizard over 13 yearsYou should mark this answer as accepted (click the green check mark next to it) so it doesn't get listed as an unanswered question.
-
Dimitris over 12 yearsHow would this work for Linux? (I believe that some libraries are not available)
-
Amit Patil about 11 years@Dimitris: it uses native Windows functions to authenticate against the domain - there's no way to do that from a non-Windows box. You'd have to reimplement the Netlogon protocol (MS-NRPC) natively, which involves implementing the underlying MS-RPC layer. Not a lot of fun.
-
Mike Pennington about 10 years@bobince, you can authenticate linux web services against an NTLM auth store using PyAuthenNTLM2 and Apache... see this blog for an example
-
Wasp over 7 years@Svetlana you should definitely mark this as an answer, the approach works nicely
-
Ami almost 7 yearsThis answer is great. It works for me! I'm in a Windows environment and want to use domain authentication. It works!!!
-
Colonel Beauvel over 6 yearswhat about a POST request? I wonder how I can handle the parameter in the Open function ...
-
imolitor about 6 yearshow would I make this approach multi-thread proof as in a Flask environment for example?