Example #1
0
    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
Example #2
0
    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