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