--- kerberos_.py 2020-03-11 15:22:10.618719193 +0100 +++ kerberos_proxy.py 2020-03-11 16:02:35.399321532 +0100 @@ -85,7 +85,10 @@ regex = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I) _negotiate_value.regex = regex - authreq = response.headers.get('www-authenticate', None) + if response.status_code == 401: + authreq = response.headers.get('www-authenticate', None) + else: + authreq = response.headers.get('proxy-authenticate', None) if authreq: match_obj = regex.search(authreq) @@ -256,6 +259,9 @@ """Handles user authentication with gssapi/kerberos""" host = urlparse(response.url).hostname + if response.status_code == 407: + if 'proxies' in kwargs and urlparse(response.url).scheme in kwargs['proxies']: + host = urlparse(kwargs['proxies'][urlparse(response.url).scheme]).hostname try: auth_header = self.generate_request_header(response, host) @@ -263,9 +269,14 @@ # GSS Failure, return existing response return response - log.debug("authenticate_user(): Authorization header: {0}".format( - auth_header)) - response.request.headers['Authorization'] = auth_header + if response.status_code == 401: + log.debug("authenticate_user(): Authorization header: {0}".format( + auth_header)) + response.request.headers['Authorization'] = auth_header + elif response.status_code == 407: + log.debug("authenticate_user(): Proxy-Authorization header: {0}".format( + auth_header)) + response.request.headers['Proxy-Authorization'] = auth_header # Consume the content so we can reuse the connection for the next # request. @@ -291,6 +302,19 @@ log.debug("handle_401(): returning {0}".format(response)) return response + def handle_407(self, response, **kwargs): + """Handles 407's, attempts to use gssapi/kerberos authentication""" + + log.debug("handle_407(): Handling: 407") + if _negotiate_value(response) is not None: + _r = self.authenticate_user(response, **kwargs) + log.debug("handle_407(): returning {0}".format(_r)) + return _r + else: + log.debug("handle_407(): Kerberos is not supported") + log.debug("handle_407(): returning {0}".format(response)) + return response + def handle_other(self, response): """Handles all responses with the exception of 401s. @@ -374,6 +398,7 @@ def handle_response(self, response, **kwargs): """Takes the given response and tries kerberos-auth, as needed.""" num_401s = kwargs.pop('num_401s', 0) + num_407s = kwargs.pop('num_407s', 0) # Check if we have already tried to get the CBT data value if not self.cbt_binding_tried and self.send_cbt: @@ -407,6 +432,19 @@ # Authentication has failed. Return the 401 response. log.debug("handle_response(): returning 401 %s", response) return response + elif response.status_code == 407 and num_407s < 2: + # 407 Unauthorized. Handle it, and if it still comes back as 407, + # that means authentication failed. + _r = self.handle_407(response, **kwargs) + log.debug("handle_response(): returning %s", _r) + log.debug("handle_response() has seen %d 407 responses", num_407s) + num_407s += 1 + return self.handle_response(_r, num_407s=num_407s, **kwargs) + elif response.status_code == 407 and num_407s >= 2: + # Still receiving 407 responses after attempting to handle them. + # Authentication has failed. Return the 407 response. + log.debug("handle_response(): returning 407 %s", response) + return response else: _r = self.handle_other(response) log.debug("handle_response(): returning %s", _r)