| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- import logging
- import urllib2
- import kerberos as krb
- class GssapiAuthError(Exception):
- """raised on error during authentication process"""
- import re
- RGX = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
- def get_negociate_value(headers):
- for authreq in headers.getheaders('www-authenticate'):
- match = RGX.search(authreq)
- if match:
- return match.group(1)
- class HTTPGssapiAuthHandler(urllib2.BaseHandler):
- """Negotiate HTTP authentication using context from GSSAPI"""
- handler_order = 400 # before Digest Auth
- def __init__(self):
- self._reset()
- def _reset(self):
- self._retried = 0
- self._context = None
- def clean_context(self):
- if self._context is not None:
- krb.authGSSClientClean(self._context)
- def http_error_401(self, req, fp, code, msg, headers):
- try:
- if self._retried > 5:
- raise urllib2.HTTPError(req.get_full_url(), 401,
- "negotiate auth failed", headers, None)
- self._retried += 1
- logging.debug('gssapi handler, try %s' % self._retried)
- negotiate = get_negociate_value(headers)
- if negotiate is None:
- logging.debug('no negociate found in a www-authenticate header')
- return None
- logging.debug('HTTPGssapiAuthHandler: negotiate 1 is %r' % negotiate)
- result, self._context = krb.authGSSClientInit("HTTP@%s" % req.get_host())
- if result < 1:
- raise GssapiAuthError("HTTPGssapiAuthHandler: init failed with %d" % result)
- result = krb.authGSSClientStep(self._context, negotiate)
- if result < 0:
- raise GssapiAuthError("HTTPGssapiAuthHandler: step 1 failed with %d" % result)
- client_response = krb.authGSSClientResponse(self._context)
- logging.debug('HTTPGssapiAuthHandler: client response is %s...' % client_response[:10])
- req.add_unredirected_header('Authorization', "Negotiate %s" % client_response)
- server_response = self.parent.open(req)
- negotiate = get_negociate_value(server_response.info())
- if negotiate is None:
- logging.warning('HTTPGssapiAuthHandler: failed to authenticate server')
- else:
- logging.debug('HTTPGssapiAuthHandler negotiate 2: %s' % negotiate)
- result = krb.authGSSClientStep(self._context, negotiate)
- if result < 1:
- raise GssapiAuthError("HTTPGssapiAuthHandler: step 2 failed with %d" % result)
- return server_response
- except GssapiAuthError, exc:
- logging.error(repr(exc))
- finally:
- self.clean_context()
- self._reset()
- if __name__ == '__main__':
- import sys
- # debug
- import httplib
- httplib.HTTPConnection.debuglevel = 1
- httplib.HTTPSConnection.debuglevel = 1
- # debug
- import logging
- logging.basicConfig(level=logging.DEBUG)
- # handle cookies
- import cookielib
- cj = cookielib.CookieJar()
- ch = urllib2.HTTPCookieProcessor(cj)
- # test with url sys.argv[1]
- h = HTTPGssapiAuthHandler()
- response = urllib2.build_opener(h, ch).open(sys.argv[1])
- print '\nresponse: %s\n--------------\n' % response.code, response.info()
|