2010-06-03 29 views
18

Estoy tratando de implementar la autenticación NTLM en IIS (Windows Server 2003) desde Windows 7 con python. Nivel de autenticación de LAN Manager: envíe solo la respuesta NTLM.
La máquina del cliente y el servidor están en el mismo dominio.
El controlador de dominio (AD) está en otro servidor (también ejecuta Windows Server 2003).Autenticación NTLM en Python

Recibo 401.1 - No autorizado: acceso denegado debido a credenciales no válidas. ¿Podría ayudarme a averiguar qué es lo que falla con este código y/o mostrarme las otras posibles instrucciones para solucionar este problema (usando NTLM o 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 está disponible aquí: https://ironpython.svn.codeplex.com/svn/IronPython_Main/External.LCA_RESTRICTED/Languages/IronPython/27/Lib/site-packages/win32/lib/sspi.py

Gracias!

Respuesta

14

He descubierto lo que estaba mal. Debería mantener viva la conexión. ¡Esa es la mercancía! Ahora este problema está resuelto.

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() 
+14

Debe marcar esta respuesta como aceptada (haga clic en la marca de verificación verde junto a él) para que no estar en la lista como una pregunta sin respuesta. –

+2

¿Cómo funcionaría esto para Linux? (Creo que algunas bibliotecas no están disponibles) – Dimitris

+0

@Dimitris: usa funciones nativas de Windows para autenticarse contra el dominio; no hay forma de hacerlo desde un cuadro que no sea de Windows. Tendría que volver a implementar el protocolo Netlogon (MS-NRPC) de forma nativa, lo que implica implementar la capa MS-RPC subyacente. No es muy divertido. – bobince

17
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 
+1

Esta respuesta es genial. ¡Esto funciona para mi! Estoy en un entorno de Windows y quiero usar la autenticación de dominio. ¡¡¡Funciona!!! – vy32

+0

¿Qué tal una solicitud POST? Me pregunto cómo puedo manejar el parámetro en la función Abrir ... –

Cuestiones relacionadas