def handle_401(self, response, **kwargs): """Takes the given response and tries digest-auth, if needed.""" original_request = response.request.copy() www_authenticate = response.headers.get('www-authenticate', '').lower() www_auth_schemes = [x.strip().split()[0] for x in www_authenticate.split(',') if x.strip()] auths_to_try = [x for x in www_auth_schemes if x in [y.lower() for y in self.auth_map.keys()]] for auth_scheme in auths_to_try: for auth_instance in self.auth_map[auth_scheme]: #print 'trying', auth_instance, 'for', auth_scheme # Consume content and release the original connection # to allow our new request to reuse the same one. response.content response.raw.release_conn() prepared_request = original_request.copy() prepared_request.hooks = default_hooks() prepared_request.prepare_auth(auth_instance) adapter = HTTPAdapter() if self.session: adapter = self.session() or adapter new_response = adapter.send(prepared_request, **kwargs) new_response.history.append(response) new_response.request = prepared_request if new_response.status_code != 401: #print auth_instance, 'successful for', auth_scheme self.current_auth = auth_instance return new_response response = new_response return response
class Foauth(BaseAdapter): """The foauth.org transport adapter.""" def __init__(self, username, password): self.auth = (username, password) self.http = HTTPAdapter() def prepare_request(self, request): p = urlparse(request.url) # Rewrite the url to use foauth.org request.url = FOAUTH_TEMPLATE.format(domain=p.netloc, path=p.path) # Authenticate appropriately. request.prepare_auth(self.auth) return request def send(self, request, **kwargs): request = self.prepare_request(request) return self.http.send(request, **kwargs)
def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): """Override base class.""" if isinstance(timeout, tuple): connect_timeout, read_timeout = timeout timeout = (self._get_timeout(connect_timeout), self._get_timeout(read_timeout)) else: timeout = self._get_timeout(timeout) return HTTPAdapter.send(self, request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
def handle_401(self, response, **kwargs): """Takes the given response and tries digest-auth, if needed.""" original_request = response.request.copy() www_authenticate = response.headers.get('www-authenticate', '').lower() www_auth_schemes = [ x.strip().split()[0] for x in www_authenticate.split(',') if x.strip() ] auths_to_try = [ x for x in www_auth_schemes if x in [y.lower() for y in self.auth_map.keys()] ] for auth_scheme in auths_to_try: for auth_instance in self.auth_map[auth_scheme]: # Consume content and release the original connection # to allow our new request to reuse the same one. response.content response.raw.release_conn() prepared_request = original_request.copy() prepared_request.hooks = default_hooks() prepared_request.prepare_auth(auth_instance) adapter = HTTPAdapter() if self.session: adapter = self.session() or adapter new_response = adapter.send(prepared_request, **kwargs) new_response.history.append(response) new_response.request = prepared_request if new_response.status_code != 401: self.current_auth = auth_instance return new_response response = new_response return response
class HttpNtlmAuth(AuthBase): """HTTP NTLM Authentication Handler for Requests. Supports pass-the-hash.""" def __init__(self, username, password): """ :username - Username in 'domain\\username' format :password - Password or hash in "ABCDABCDABCDABCD:ABCDABCDABCDABCD" format. """ if ntlm is None: raise Exception("NTLM libraries unavailable") #parse the username try: self.domain, self.username = username.split('\\', 1) except ValueError: raise ValueError("username should be in 'domain\\username' format.") self.domain = self.domain.upper() self.password = password self.adapter = HTTPAdapter() def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = copy_request(response.request) # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" # A streaming response breaks authentication. # This can be fixed by not streaming this request, which is safe because # the returned response3 will still have stream=True set if specified in # args. In addition, we expect this request to give us a challenge # and not the real content, so the content will be short anyway. args_nostream = dict(args, stream=False) response2 = self.adapter.send(request, **args_nostream) # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ntlm_header_value = list(filter(lambda s: s.startswith('NTLM '), auth_header_value.split(',')))[0].strip() ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_header_value[5:]) # build response request = copy_request(request) auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth response3 = self.adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3 def response_hook(self, r, **kwargs): if r.status_code == 401 and 'ntlm' in r.headers.get('www-authenticate','').lower(): return self.retry_using_http_NTLM_auth('www-authenticate', 'Authorization', r, kwargs) if r.status_code == 407 and 'ntlm' in r.headers.get('proxy-authenticate','').lower(): return self.retry_using_http_NTLM_auth('proxy-authenticate', 'Proxy-authorization', r, kwargs) return r def __call__(self, r): r.register_hook('response', self.response_hook) return r
def send(self, *args, **kwargs): if kwargs.get("timeout") is None: kwargs["timeout"] = self.default_timeout return HTTPAdapter.send(self, *args, **kwargs)
class HttpNtlmAuth(AuthBase): """HTTP NTLM Authentication Handler for Requests. Supports pass-the-hash.""" def __init__(self, username, password): """ :username - Username in 'domain\\username' format :password - Password or hash in "ABCDABCDABCDABCD:ABCDABCDABCDABCD" format. """ if ntlm is None: raise Exception("NTLM libraries unavailable") #parse the username user_parts = username.split('\\', 1) self.domain = user_parts[0].upper() self.username = user_parts[1] self.password = password self.adapter = HTTPAdapter() def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response, args): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = copy_request(response.request) # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" # A streaming response breaks authentication. # This can be fixed by not streaming this request, which is safe because # the returned response3 will still have stream=True set if specified in # args. In addition, we expect this request to give us a challenge # and not the real content, so the content will be short anyway. args_nostream = dict(args, stream=False) response2 = self.adapter.send(request, **args_nostream) # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): request.headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:]) # build response request = copy_request(request) auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth response3 = self.adapter.send(request, **args) # Update the history. response3.history.append(response) response3.history.append(response2) return response3 def response_hook(self, r, **kwargs): if r.status_code == 401 and 'ntlm' in r.headers.get('www-authenticate','').lower(): return self.retry_using_http_NTLM_auth('www-authenticate', 'Authorization', r, kwargs) if r.status_code == 407 and 'ntlm' in r.headers.get('proxy-authenticate','').lower(): return self.retry_using_http_NTLM_auth('proxy-authenticate', 'Proxy-authorization', r, kwargs) return r def __call__(self, r): r.register_hook('response', self.response_hook) return r
def send(self, request, **kwargs): kwargs['timeout'] = kwargs.get('timeout', self.timeout) return HTTPAdapter.send(self, request, **kwargs)
class HttpNtlmAuth(AuthBase): """HTTP NTLM Authentication Handler for Requests. Supports pass-the-hash.""" def __init__(self, username, password): """ :username - Username in 'domain\\username' format :password - Password or hash in "ABCDABCDABCDABCD:ABCDABCDABCDABCD" format. """ if ntlm is None: raise Exception("NTLM libraries unavailable") #parse the username user_parts = username.split('\\', 1) self.domain = user_parts[0].upper() self.username = user_parts[1] self.password = password self.adapter = HTTPAdapter() def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = response.request # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" response2 = self.adapter.send(request) # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:]) # build response auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth request.headers["Connection"] = "Close" response = self.adapter.send(request) return response def response_hook(self,r): if r.status_code == 401 and 'ntlm' in r.headers.get('www-authenticate','').lower(): return self.retry_using_http_NTLM_auth('www-authenticate', 'Authorization', r) if r.status_code == 407 and 'ntlm' in r.headers.get('proxy-authenticate','').lower(): return self.retry_using_http_NTLM_auth('proxy-authenticate', 'Proxy-authorization', r) return r def __call__(self,r): r.register_hook('response', self.response_hook) return r
class HttpNtlmAuth(AuthBase): """HTTP NTLM Authentication Handler for Requests. Supports pass-the-hash.""" def __init__(self, username, password): """ :username - Username in 'domain\\username' format :password - Password or hash in "ABCDABCDABCDABCD:ABCDABCDABCDABCD" format. """ if ntlm is None: raise Exception("NTLM libraries unavailable") #parse the username user_parts = username.split('\\', 1) self.domain = user_parts[0].upper() self.username = user_parts[1] self.password = password self.adapter = HTTPAdapter() def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response): """Attempts to authenticate using HTTP NTLM challenge/response""" if auth_header in response.request.headers: return response request = response.request # initial auth header with username. will result in challenge auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE( "%s\\%s" % (self.domain, self.username)) request.headers[auth_header] = auth # we must keep the connection because NTLM authenticates the connection, not single requests request.headers["Connection"] = "Keep-Alive" response2 = self.adapter.send(request) # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out) if response2.headers.get('set-cookie'): headers['Cookie'] = response2.headers.get('set-cookie') # get the challenge auth_header_value = response2.headers[auth_header_field] ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE( auth_header_value[5:]) # build response auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE( ServerChallenge, self.username, self.domain, self.password, NegotiateFlags) request.headers[auth_header] = auth request.headers["Connection"] = "Close" response = self.adapter.send(request) return response def response_hook(self, r): if r.status_code == 401 and 'ntlm' in r.headers.get( 'www-authenticate', '').lower(): return self.retry_using_http_NTLM_auth('www-authenticate', 'Authorization', r) if r.status_code == 407 and 'ntlm' in r.headers.get( 'proxy-authenticate', '').lower(): return self.retry_using_http_NTLM_auth('proxy-authenticate', 'Proxy-authorization', r) return r def __call__(self, r): r.register_hook('response', self.response_hook) return r
class BetamaxAdapter(BaseAdapter): """This object is an implementation detail of the library. It is not meant to be a public API and is not exported as such. """ def __init__(self, **kwargs): super(BetamaxAdapter, self).__init__() self.cassette = None self.cassette_name = None self.http_adapter = HTTPAdapter(**kwargs) self.serialize = None self.options = {} def cassette_exists(self): if self.cassette_name and os.path.exists(self.cassette_name): return True return False def close(self): self.http_adapter.close() def eject_cassette(self): if self.cassette: self.cassette.eject() self.cassette = None # Allow self.cassette to be garbage-collected def load_cassette(self, cassette_name, serialize, options): self.cassette_name = cassette_name self.serialize = serialize self.options.update(options) placeholders = self.options.get('placeholders') # load cassette into memory if self.cassette_exists(): self.cassette = Cassette(cassette_name, serialize, placeholders=placeholders) elif os.path.exists(os.path.dirname(cassette_name)): self.cassette = Cassette(cassette_name, serialize, 'w+', placeholders=placeholders) else: raise RuntimeError( 'No cassette could be loaded or %s does not exist.' % os.path.dirname(cassette_name) ) self.cassette.record_mode = self.options['record'] re_record_interval = timedelta.max if self.options.get('re_record_interval'): re_record_interval = timedelta(self.options['re_record_interval']) now = datetime.utcnow() if re_record_interval < (now - self.cassette.earliest_recorded_date): self.cassette.clear() def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): interaction = None match_on = Cassette.default_cassette_options['match_requests_on'] response = None if not self.cassette: raise BetamaxError('No cassette was specified or found.') if self.cassette.interactions: self.cassette.match_options = set(match_on) interaction = self.cassette.find_match(request) if not interaction and self.cassette.is_recording(): response = self.http_adapter.send( request, stream=True, timeout=timeout, verify=verify, cert=cert, proxies=proxies ) self.cassette.save_interaction(response, request) interaction = self.cassette.interactions[-1] if not interaction: raise BetamaxError('A request was made that could not be handled') return interaction.as_response()