OLD | NEW |
(Empty) | |
| 1 from __future__ import print_function |
| 2 |
| 3 import logging |
| 4 import urllib2 |
| 5 |
| 6 import kerberos as krb |
| 7 |
| 8 class GssapiAuthError(Exception): |
| 9 """raised on error during authentication process""" |
| 10 |
| 11 import re |
| 12 RGX = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I) |
| 13 |
| 14 def get_negociate_value(headers): |
| 15 for authreq in headers.getheaders('www-authenticate'): |
| 16 match = RGX.search(authreq) |
| 17 if match: |
| 18 return match.group(1) |
| 19 |
| 20 class HTTPGssapiAuthHandler(urllib2.BaseHandler): |
| 21 """Negotiate HTTP authentication using context from GSSAPI""" |
| 22 |
| 23 handler_order = 400 # before Digest Auth |
| 24 |
| 25 def __init__(self): |
| 26 self._reset() |
| 27 |
| 28 def _reset(self): |
| 29 self._retried = 0 |
| 30 self._context = None |
| 31 |
| 32 def clean_context(self): |
| 33 if self._context is not None: |
| 34 krb.authGSSClientClean(self._context) |
| 35 |
| 36 def http_error_401(self, req, fp, code, msg, headers): |
| 37 try: |
| 38 if self._retried > 5: |
| 39 raise urllib2.HTTPError(req.get_full_url(), 401, |
| 40 "negotiate auth failed", headers, None) |
| 41 self._retried += 1 |
| 42 logging.debug('gssapi handler, try %s' % self._retried) |
| 43 negotiate = get_negociate_value(headers) |
| 44 if negotiate is None: |
| 45 logging.debug('no negociate found in a www-authenticate header') |
| 46 return None |
| 47 logging.debug('HTTPGssapiAuthHandler: negotiate 1 is %r' % negotiate
) |
| 48 result, self._context = krb.authGSSClientInit("HTTP@%s" % req.get_ho
st()) |
| 49 if result < 1: |
| 50 raise GssapiAuthError("HTTPGssapiAuthHandler: init failed with %
d" % result) |
| 51 result = krb.authGSSClientStep(self._context, negotiate) |
| 52 if result < 0: |
| 53 raise GssapiAuthError("HTTPGssapiAuthHandler: step 1 failed with
%d" % result) |
| 54 client_response = krb.authGSSClientResponse(self._context) |
| 55 logging.debug('HTTPGssapiAuthHandler: client response is %s...' % cl
ient_response[:10]) |
| 56 req.add_unredirected_header('Authorization', "Negotiate %s" % client
_response) |
| 57 server_response = self.parent.open(req) |
| 58 negotiate = get_negociate_value(server_response.info()) |
| 59 if negotiate is None: |
| 60 logging.warning('HTTPGssapiAuthHandler: failed to authenticate s
erver') |
| 61 else: |
| 62 logging.debug('HTTPGssapiAuthHandler negotiate 2: %s' % negotiat
e) |
| 63 result = krb.authGSSClientStep(self._context, negotiate) |
| 64 if result < 1: |
| 65 raise GssapiAuthError("HTTPGssapiAuthHandler: step 2 failed
with %d" % result) |
| 66 return server_response |
| 67 except GssapiAuthError as exc: |
| 68 logging.error(repr(exc)) |
| 69 finally: |
| 70 self.clean_context() |
| 71 self._reset() |
| 72 |
| 73 if __name__ == '__main__': |
| 74 import sys |
| 75 # debug |
| 76 import httplib |
| 77 httplib.HTTPConnection.debuglevel = 1 |
| 78 httplib.HTTPSConnection.debuglevel = 1 |
| 79 # debug |
| 80 import logging |
| 81 logging.basicConfig(level=logging.DEBUG) |
| 82 # handle cookies |
| 83 import cookielib |
| 84 cj = cookielib.CookieJar() |
| 85 ch = urllib2.HTTPCookieProcessor(cj) |
| 86 # test with url sys.argv[1] |
| 87 h = HTTPGssapiAuthHandler() |
| 88 response = urllib2.build_opener(h, ch).open(sys.argv[1]) |
| 89 print('\nresponse: %s\n--------------\n' % response.code, response.info()) |
OLD | NEW |