def validate(username, password, domain=""): auth_info = username, domain, password ca = ClientAuth("NTLM", auth_info=auth_info) sa = ServerAuth("NTLM") data = err = None while err != 0: err, data = ca.authorize(data) err, data = sa.authorize(data)
def validate(username, password, domain = ""): auth_info = username, domain, password ca = ClientAuth("NTLM", auth_info = auth_info) sa = ServerAuth("NTLM") data = err = None while err != 0: err, data = ca.authorize(data) err, data = sa.authorize(data)
def http_error_401(self, req, fp, code, msg, headers): supported_schemes = [s.strip() for s in headers.get("WWW-Authenticate", "").split(",")] #dns_domain = os.environ['USERDNSDOMAIN'] dns_domain = 'tranquilit.local' if('Negotiate' in supported_schemes): try: ca = ClientAuth("Kerberos", targetspn='HTTP/%s@%s' % (req.host.split(':')[0], dns_domain), auth_info=None) out_buf = ca.authorize(None)[1] data = out_buf[0].Buffer auth = encodestring(data).replace("\012", "") req.add_header('Authorization', 'Negotiate' + ' ' + auth) return self.parent.open(req) except: if('Kerberos' not in supported_schemes): # if we can not fall back to NTLM, report error raise
def http_error_401(self, req, fp, code, msg, headers): supported_schemes = [ s.strip() for s in headers.get("WWW-Authenticate", "").split(",") ] #dns_domain = os.environ['USERDNSDOMAIN'] dns_domain = 'tranquilit.local' if ('Negotiate' in supported_schemes): try: ca = ClientAuth("Kerberos", targetspn='HTTP/%s@%s' % (req.host.split(':')[0], dns_domain), auth_info=None) out_buf = ca.authorize(None)[1] data = out_buf[0].Buffer auth = encodestring(data).replace("\012", "") req.add_header('Authorization', 'Negotiate' + ' ' + auth) return self.parent.open(req) except: if ('Kerberos' not in supported_schemes): # if we can not fall back to NTLM, report error raise
def open_url(host, url): h = httplib.HTTPConnection(host) # h.set_debuglevel(9) h.putrequest('GET', url) h.endheaders() resp = h.getresponse() print "Initial response is", resp.status, resp.reason body = resp.read() if resp.status == 302: # object moved url = "/" + resp.msg["location"] resp.close() h.putrequest('GET', url) h.endheaders() resp = h.getresponse() print "After redirect response is", resp.status, resp.reason if options.show_headers: print "Initial response headers:" for name, val in resp.msg.items(): print " %s: %s" % (name, val) if options.show_body: print body if resp.status == 401: # 401: Unauthorized - here is where the real work starts auth_info = None if options.user or options.domain or options.password: auth_info = options.user, options.domain, options.password ca = ClientAuth("NTLM", auth_info=auth_info) auth_scheme = ca.pkg_info['Name'] data = None while 1: err, out_buf = ca.authorize(data) data = out_buf[0].Buffer # Encode it as base64 as required by HTTP auth = encodestring(data).replace("\012", "") h.putrequest('GET', url) h.putheader('Authorization', auth_scheme + ' ' + auth) h.putheader('Content-Length', '0') h.endheaders() resp = h.getresponse() if options.show_headers: print "Token dance headers:" for name, val in resp.msg.items(): print " %s: %s" % (name, val) if err==0: break else: if resp.status != 401: print "Eeek - got response", resp.status cl = resp.msg.get("content-length") if cl: print repr(resp.read(int(cl))) else: print "no content!" assert resp.status == 401, resp.status assert not resp.will_close, "NTLM is per-connection - must not close" schemes = [s.strip() for s in resp.msg.get("WWW-Authenticate", "").split(",")] for scheme in schemes: if scheme.startswith(auth_scheme): data = decodestring(scheme[len(auth_scheme)+1:]) break else: print "Could not find scheme '%s' in schemes %r" % (auth_scheme, schemes) break resp.read() print "Final response status is", resp.status, resp.reason if resp.status == 200: # Worked! # Check we can read it again without re-authenticating. if resp.will_close: print "EEEK - response will close, but NTLM is per connection - it must stay open" body = resp.read() if options.show_body: print "Final response body:" print body h.putrequest('GET', url) h.endheaders() resp = h.getresponse() print "Second fetch response is", resp.status, resp.reason if options.show_headers: print "Second response headers:" for name, val in resp.msg.items(): print " %s: %s" % (name, val) resp.read(int(resp.msg.get("content-length", 0))) elif resp.status == 500: print "Error text" print resp.read() else: if options.show_body: cl = resp.msg.get("content-length") print resp.read(int(cl))
def open_url(host, url): h = http.client.HTTPConnection(host) # h.set_debuglevel(9) h.putrequest('GET', url) h.endheaders() resp = h.getresponse() print("Initial response is", resp.status, resp.reason) body = resp.read() if resp.status == 302: # object moved url = "/" + resp.msg["location"] resp.close() h.putrequest('GET', url) h.endheaders() resp = h.getresponse() print("After redirect response is", resp.status, resp.reason) if options.show_headers: print("Initial response headers:") for name, val in list(resp.msg.items()): print(" %s: %s" % (name, val)) if options.show_body: print(body) if resp.status == 401: # 401: Unauthorized - here is where the real work starts auth_info = None if options.user or options.domain or options.password: auth_info = options.user, options.domain, options.password ca = ClientAuth("NTLM", auth_info=auth_info) auth_scheme = ca.pkg_info['Name'] data = None while 1: err, out_buf = ca.authorize(data) data = out_buf[0].Buffer # Encode it as base64 as required by HTTP auth = encodestring(data).replace("\012", "") h.putrequest('GET', url) h.putheader('Authorization', auth_scheme + ' ' + auth) h.putheader('Content-Length', '0') h.endheaders() resp = h.getresponse() if options.show_headers: print("Token dance headers:") for name, val in list(resp.msg.items()): print(" %s: %s" % (name, val)) if err == 0: break else: if resp.status != 401: print("Eeek - got response", resp.status) cl = resp.msg.get("content-length") if cl: print(repr(resp.read(int(cl)))) else: print("no content!") assert resp.status == 401, resp.status assert not resp.will_close, "NTLM is per-connection - must not close" schemes = [ s.strip() for s in resp.msg.get("WWW-Authenticate", "").split(",") ] for scheme in schemes: if scheme.startswith(auth_scheme): data = decodestring(scheme[len(auth_scheme) + 1:]) break else: print("Could not find scheme '%s' in schemes %r" % (auth_scheme, schemes)) break resp.read() print("Final response status is", resp.status, resp.reason) if resp.status == 200: # Worked! # Check we can read it again without re-authenticating. if resp.will_close: print( "EEEK - response will close, but NTLM is per connection - it must stay open" ) body = resp.read() if options.show_body: print("Final response body:") print(body) h.putrequest('GET', url) h.endheaders() resp = h.getresponse() print("Second fetch response is", resp.status, resp.reason) if options.show_headers: print("Second response headers:") for name, val in list(resp.msg.items()): print(" %s: %s" % (name, val)) resp.read(int(resp.msg.get("content-length", 0))) elif resp.status == 500: print("Error text") print(resp.read()) else: if options.show_body: cl = resp.msg.get("content-length") print(resp.read(int(cl)))
class HttpNtlmSspiAuth(AuthBase): """Requests extension to auto-authenticate user. HTTP NTLM Authentication using SSPI for passwordless login. """ def __init__(self): self.AuthGen = ClientAuth("NTLM") def __call__(self, r): r.headers["Connection"] = "Keep-Alive" r.register_hook("response", self.response_hook) return r def response_hook(self, r, **kwargs): """ Identifies the type of authentication needed and the header title and routes the information to perform the authentication dance """ www_authenticate = r.headers.get("www-authenticate", "").lower() if r.status_code == 401 and "ntlm" in www_authenticate: return self.apply_sspi("www-authenticate", "Authorization", r, kwargs) proxy_authenticate = r.headers.get("proxy-authenticate", "").lower() if r.status_code == 407 and "ntlm" in proxy_authenticate: return self.apply_sspi("proxy-authenticate", "Proxy-authorization", r, kwargs) return r def authenticate(self, challenge=None): """Performs the authentication handshake Parameters ---------- challenge : str, optional Challenge is the response encoded response from the web-server that is typically the response to the client's initial challenge. When `challenge` is called without a `challenge`, it generates the first challenge to the server that open the communication between them. Returns ------- str Returns a challenge for the server. That will either initiate the communication, or respond to the webservice's challenge. """ challenge = challenge.decode("base64") if challenge else None _, output_buffer = self.AuthGen.authorize(challenge) return "NTLM {0!s}".format(output_buffer[0].Buffer.encode("base64").replace("\n", "")) def new_request(self, response): response.content response.raw.release_conn() return response.request.copy() def apply_sspi(self, auth_header_field, auth_header, response, args): """Performs the authentication dance between server and client. """ if auth_header in response.request.headers: return response # A streaming response breaks authentication. Disabled for authentication dance # set back to default (args) for final return request = self.new_request(response) request.headers[auth_header] = self.authenticate() response = response.connection.send(request, **dict(args, stream=False)) # Previous request/response sent initial msg to begin dance. # Now we authenticate using the response request = self.new_request(response) ntlm_header_value = response.headers[auth_header_field][5:] request.headers[auth_header] = self.authenticate(ntlm_header_value) # In case authentication info stored in cookies request.headers["Cookie"] = response.headers.get("set-cookie") return response.connection.send(request, **args)