aboutsummaryrefslogtreecommitdiffstats
path: root/urllib2_kerberos.py
diff options
context:
space:
mode:
authorUnknown <tolsen@limebits.com>2008-06-26 14:16:48 -0400
committerMatěj Cepl <mcepl@cepl.eu>2023-04-29 18:17:45 +0200
commita58af31d7e91494afe7951c1b345de3944054572 (patch)
tree9e54becb5b40d9c3640ff91b5a7b803c8ddbdea8 /urllib2_kerberos.py
parentaee7fa60cd9c8f781f8c7280c4e6471f97641ba3 (diff)
downloadurllib2_kerberos-a58af31d7e91494afe7951c1b345de3944054572.tar.gz
rename http_kerberos_auth_handler.py to urllib2_kerberos.py
Diffstat (limited to 'urllib2_kerberos.py')
-rw-r--r--urllib2_kerberos.py141
1 files changed, 40 insertions, 101 deletions
diff --git a/urllib2_kerberos.py b/urllib2_kerberos.py
index 84542bd..bf08042 100644
--- a/urllib2_kerberos.py
+++ b/urllib2_kerberos.py
@@ -1,21 +1,20 @@
#!/usr/bin/python
# urllib2 with kerberos proof of concept
-
-# Copyright 2008 Lime Nest LLC
# Copyright 2008 Lime Spot LLC
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
-# http://www.apache.org/licenses/LICENSE-2.0
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
import logging
@@ -24,7 +23,6 @@ import urllib2 as u2
import kerberos as k
-
def getLogger():
log = logging.getLogger("http_kerberos_auth_handler")
handler = logging.StreamHandler()
@@ -34,30 +32,26 @@ def getLogger():
return log
log = getLogger()
-log.setLevel(logging.DEBUG)
-
-class AbstractKerberosAuthHandler:
- """auth handler for urllib2 that does Kerberos HTTP Negotiate
- Authentication
+class HTTPKerberosAuthHandler(u2.BaseHandler):
+ """auth handler for urllib2 that does Kerberos HTTP Negotiate Authentication
"""
+ rx = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
+ handler_order = 480 # before Digest auth
+
def negotiate_value(self, headers):
- """checks for "Negotiate" in proper auth header
- """
- authreq = headers.get(self.auth_header, None)
- log.debug('authreq = {}'.format(authreq))
+ authreq = headers.get('www-authenticate', None)
if authreq:
- rx = re.compile(r'(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
- mo = rx.search(authreq)
+ mo = HTTPKerberosAuthHandler.rx.search(authreq)
if mo:
return mo.group(1)
else:
log.debug("regex failed on: %s" % authreq)
else:
- log.debug("%s header not found" % self.auth_header)
+ log.debug("www-authenticate header not found")
return None
@@ -65,16 +59,20 @@ class AbstractKerberosAuthHandler:
self.retried = 0
self.context = None
- def generate_request_header(self, req, headers, neg_value):
- self.retried += 1
- log.debug("retry count: %d" % self.retried)
+ def generate_request_header(self, req, headers):
+ neg_value = self.negotiate_value(headers)
+ if neg_value is None:
+ self.retried = 0
+ return None
- host = req.get_host()
- log.debug("req.get_host() returned %s" % host)
+ if self.retried > 5:
+ raise HTTPError(req.get_full_url(), 401, "kerberos negotiate auth failed",
+ headers, None)
- domain = host.rsplit(':', 1)[0]
+ self.retried += 1
- result, self.context = k.authGSSClientInit("HTTP@%s" % domain)
+ log.debug("req.get_host() returned %s" % req.get_host())
+ result, self.context = k.authGSSClientInit("HTTP@%s" % req.get_host())
if result < 1:
log.warning("authGSSClientInit returned result %d" % result)
@@ -92,7 +90,7 @@ class AbstractKerberosAuthHandler:
response = k.authGSSClientResponse(self.context)
log.debug("authGSSClientResponse() succeeded")
-
+
return "Negotiate %s" % response
def authenticate_server(self, headers):
@@ -101,90 +99,31 @@ class AbstractKerberosAuthHandler:
log.critical("mutual auth failed. No negotiate header")
return None
- result = k.authGSSClientStep(self.context, neg_value)
-
- if result < 1:
- # this is a critical security warning
- # should change to a raise --Tim
- log.critical(
- "mutual auth failed: authGSSClientStep returned result %d" %
- result)
+ if k.authGSSClientStep(self.context, neg_value) < 1:
+ log.critical("mutual auth failed: authGSSClientStep returned result %d" % result)
def clean_context(self):
if self.context is not None:
- log.debug("cleaning context")
k.authGSSClientClean(self.context)
- self.context = None
-
- def http_error_auth_reqed(self, host, req, headers):
- neg_value = self.negotiate_value(headers) # Check for auth_header
- if neg_value is not None:
- if not self.retried > 0:
- return self.retry_http_kerberos_auth(req, headers, neg_value)
- else:
- return None
- else:
- self.retried = 0
- def retry_http_kerberos_auth(self, req, headers, neg_value):
+ def http_error_401(self, req, fp, code, msg, headers):
+ log.debug("inside http_error_401")
try:
- neg_hdr = self.generate_request_header(req, headers, neg_value)
+ neg_hdr = self.generate_request_header(req, headers)
if neg_hdr is None:
log.debug("neg_hdr was None")
return None
- req.add_unredirected_header(self.authz_header, neg_hdr)
+ req.add_unredirected_header('Authorization', neg_hdr)
resp = self.parent.open(req)
- if resp.getcode() != 200:
- self.authenticate_server(resp.info())
+ self.authenticate_server(resp.info())
return resp
-
- except k.GSSError, e:
+
+ finally:
self.clean_context()
- self.retried = 0
- log.critical("GSSAPI Error: %s/%s" % (e[0][0], e[1][0]))
- return None
-
- self.clean_context()
- self.retried = 0
-
-
-class ProxyKerberosAuthHandler(u2.BaseHandler, AbstractKerberosAuthHandler):
- """Kerberos Negotiation handler for HTTP proxy auth
- """
-
- authz_header = 'Proxy-Authorization'
- auth_header = 'proxy-authenticate'
-
- handler_order = 480 # before Digest auth
-
- def http_error_407(self, req, fp, code, msg, headers):
- log.debug("inside http_error_407")
- host = req.get_host()
- retry = self.http_error_auth_reqed(host, req, headers)
- self.retried = 0
- return retry
-
-
-class HTTPKerberosAuthHandler(u2.BaseHandler, AbstractKerberosAuthHandler):
- """Kerberos Negotiation handler for HTTP auth
- """
-
- authz_header = 'Authorization'
- auth_header = 'www-authenticate'
-
- handler_order = 480 # before Digest auth
-
- def http_error_401(self, req, fp, code, msg, headers):
- log.debug("inside http_error_401")
- host = req.get_host()
- retry = self.http_error_auth_reqed(host, req, headers)
- self.retried = 0
- return retry
-
def test():
log.setLevel(logging.DEBUG)
@@ -193,7 +132,7 @@ def test():
opener.add_handler(HTTPKerberosAuthHandler())
resp = opener.open(sys.argv[1])
print dir(resp), resp.info(), resp.code
-
+
if __name__ == '__main__':
test()