def authenticate(self, response): ''' Perform authentication if the response requests it and enabled by the options set @param response: A response being processed @type response: L{HttxResponse} @return: The same response preocessed @rtype: L{HttxResponse} ''' authheaderserver = {401:'www-authenticate', 407:'proxy-authenticate'} authheaderclient = {401:'authorization', 407:'proxy-authorization'} if not self.options.auth: return response if response.isauthuser() and not self.options.authuser: return response if response.isauthproxy() and not self.options.authproxy: return response authheader = response.getheader(authheaderserver[response.status]) authscheme, authchallenge = authheader.split(' ', 1) authscheme = authscheme.lower() authchallenge = parse_keqv_list(parse_http_list(authchallenge)) realm = authchallenge['realm'] username, password = self.options.passmanager.find_user_password(realm, self.lastreq.get_full_url()) # None is "not empty strings" if username is None or password is None: return response authanswer = None authcachedata = None if authscheme == 'basic': authanswer, authcachedata = authbasic(username, password, authchallenge) elif authscheme == 'digest': if 'nonce' in authchallenge: nonce_count = self.options.authcache.getnoncecount(authchallenge['nonce']) authanswer, authcachedata = authdigest(username, password, authchallenge, self.lastreq, nonce_count) else: # XXX Pluggable authhandlers # authhandler = self.options.authhandler.get(authscheme) # authanswer, authcachedata = authhandler(username, password, authchallenge) pass if not authanswer: return response authorization = '%s %s' % (authscheme, authanswer) # Create a clone of the request with the new url authreq = self.lastreq authreq.add_unredirected_header(authheaderclient[response.status], authorization) response.sock = self.request(authreq) self.auxhttx = self # store it together with the authorization string - with parsed.url parsed = urlsplit(authreq.get_full_url()) self.options.authcache.set(parsed.geturl(), authheaderclient[response.status], authscheme, authcachedata) return response
def authenticate(self, response): ''' Perform authentication if the response requests it and enabled by the options set @param response: A response being processed @type response: L{HttxResponse} @return: The same response preocessed @rtype: L{HttxResponse} ''' authheaderserver = {401: 'www-authenticate', 407: 'proxy-authenticate'} authheaderclient = {401: 'authorization', 407: 'proxy-authorization'} if not self.options.auth: return response if response.isauthuser() and not self.options.authuser: return response if response.isauthproxy() and not self.options.authproxy: return response authheader = response.getheader(authheaderserver[response.status]) authscheme, authchallenge = authheader.split(' ', 1) authscheme = authscheme.lower() authchallenge = parse_keqv_list(parse_http_list(authchallenge)) realm = authchallenge['realm'] username, password = self.options.passmanager.find_user_password( realm, self.lastreq.get_full_url()) # None is "not empty strings" if username is None or password is None: return response authanswer = None authcachedata = None if authscheme == 'basic': authanswer, authcachedata = authbasic(username, password, authchallenge) elif authscheme == 'digest': if 'nonce' in authchallenge: nonce_count = self.options.authcache.getnoncecount( authchallenge['nonce']) authanswer, authcachedata = authdigest(username, password, authchallenge, self.lastreq, nonce_count) else: # XXX Pluggable authhandlers # authhandler = self.options.authhandler.get(authscheme) # authanswer, authcachedata = authhandler(username, password, authchallenge) pass if not authanswer: return response authorization = '%s %s' % (authscheme, authanswer) # Create a clone of the request with the new url authreq = self.lastreq authreq.add_unredirected_header(authheaderclient[response.status], authorization) response.sock = self.request(authreq) self.auxhttx = self # store it together with the authorization string - with parsed.url parsed = urlsplit(authreq.get_full_url()) self.options.authcache.set(parsed.geturl(), authheaderclient[response.status], authscheme, authcachedata) return response
def authenticate(self, response, plaintunnel=False): ''' Perform authentication if the response requests it and enabled by the options set @param response: A response being processed @type response: L{HttxResponse} @return: The same response preocessed @rtype: L{HttxResponse} ''' authheaderserver = {401:'www-authenticate', 407:'proxy-authenticate'} authheaderclient = {401:'authorization', 407:'proxy-authorization'} if not self.options.auth: return response if response.isauthuser() and not self.options.authuser: return response if response.isauthproxy() and not self.options.authproxy: return response # This will return several "xxx-authenticate" into a "," separated list authheader = response.getheader(authheaderserver[response.status]) # Parse a potentially multi-challenge header authschemes = dict() lastscheme = None # parse a list of ',' separated values ... some challenges, some params to challenges # some a challenge plus a param for elem in parse_http_list(authheader): authparts = elem.split(' ', 1) if lastscheme and '=' in authparts[0]: # parameter, it must belong to previous scheme authschemes[lastscheme].append(authparts[0]) continue # else new scheme lastscheme = authparts[0].lower() authschemes[lastscheme] = list() # we may still have the 1st parameter (because the 1st is "sp" separated and not "," separated) if len(authparts) > 1: authschemes[lastscheme].append(authparts[1]) for scheme, keqv_list in authschemes.iteritems(): authschemes[scheme] = parse_keqv_list(keqv_list) # if 401, we authenticate against the request we sent and not where the connection points to # because that is a 407 then: a proxy and we authenticate against the proxy url authurl = self.lastreq.get_full_url() if response.status == 401 else self.url authscheme = None authanswer = None authcachedata = None if self.options.authhandler: authcachedata = self.options.authcache.get(authurl, opaque=True) authscheme, authanswer, authcachedata = self.options.authhandler(authurl, authschemes, authcachedata) if authscheme is None or authanswer is None: # No external handling (absent or not capable) - try internal ones if 'digest' in authschemes: authchallenge = authschemes['digest'] realm = authchallenge.get('realm', None) username, password = self.options.passmanager.find_user_password(realm, authurl) if 'nonce' in authchallenge: nonce_count = self.options.authcache.getnoncecount(authchallenge['nonce']) authscheme, authanswer, authcachedata = authdigest(username, password, authchallenge, self.lastreq, nonce_count) elif 'basic' in authschemes: authchallenge = authschemes['basic'] realm = authchallenge.get('realm', None) username, password = self.options.passmanager.find_user_password(realm, authurl) if username is not None and password is not None: authscheme, authanswer, authcachedata = authbasic(username, password, authchallenge) if authscheme is None or authanswer is None: return response # Generate the authorization authorization = '%s %s' % (authscheme, authanswer) # Choose the response authorization header authheaderresp = authheaderclient[response.status] # Create a clone of the request with the new url authreq = self.lastreq authreq.add_unredirected_header(authheaderresp, authorization) # Remember type of tunnel if "connect" has to be attempted after auth (obviously via a proxy) authreq.plaintunnel = plaintunnel if authcachedata is not None: # store it together with the authorization string - with parsed.url self.options.authcache.set(authreq.parsed.geturl(), authheaderresp, authscheme, authanswer, authcachedata) response.sock = self.request(authreq) self.auxhttx = self return response