summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2001-11-09 16:46:51 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2001-11-09 16:46:51 (GMT)
commit52a17becbcc8bba8d4750926c58f6ac6e41464b7 (patch)
tree3fe54eea69cba3a671c9d03d85d9ee179bc58b55 /Lib
parent6383c2d1a677f168ed2a4dfc9cb28f93ec327a0e (diff)
downloadcpython-52a17becbcc8bba8d4750926c58f6ac6e41464b7.zip
cpython-52a17becbcc8bba8d4750926c58f6ac6e41464b7.tar.gz
cpython-52a17becbcc8bba8d4750926c58f6ac6e41464b7.tar.bz2
Fix SF bug 468948 & 451295: urllib2 authentication problems
Fix contributed by Jeffrey C. Ollie. I haven't tested the fix because the situation is non-trivial to reproduce. The basic solution is to get rid of the __current_realm attribute of authentication handlers. Instead, prevent infinite retries by checking for the presence of an Authenticate: header in the request object that exactly matches the Authenticate: header that would be added. The problem prevent authentication from working correctly in the presence of retries. Ollie mentioned that digest authentication has the same problem and I applied the same solution there.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/urllib2.py40
1 files changed, 12 insertions, 28 deletions
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index 3f01554..ffd73b8 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -578,11 +578,6 @@ class AbstractBasicAuthHandler:
password_mgr = HTTPPasswordMgr()
self.passwd = password_mgr
self.add_password = self.passwd.add_password
- self.__current_realm = None
- # if __current_realm is not None, then the server must have
- # refused our name/password and is asking for authorization
- # again. must be careful to set it to None on successful
- # return.
def http_error_auth_reqed(self, authreq, host, req, headers):
# XXX could be multiple headers
@@ -595,26 +590,20 @@ class AbstractBasicAuthHandler:
return self.retry_http_basic_auth(host, req, realm)
def retry_http_basic_auth(self, host, req, realm):
- if self.__current_realm is None:
- self.__current_realm = realm
- else:
- self.__current_realm = realm
- return None
user,pw = self.passwd.find_user_password(realm, host)
if pw:
raw = "%s:%s" % (user, pw)
- auth = base64.encodestring(raw).strip()
- req.add_header(self.header, 'Basic %s' % auth)
- resp = self.parent.open(req)
- self.__current_realm = None
- return resp
+ auth = 'Basic %s' % base64.encodestring(raw).strip()
+ if req.headers.get(self.auth_header, None) == auth:
+ return None
+ req.add_header(self.auth_header, auth)
+ return self.parent.open(req)
else:
- self.__current_realm = None
return None
class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
- header = 'Authorization'
+ auth_header = 'Authorization'
def http_error_401(self, req, fp, code, msg, headers):
host = urlparse.urlparse(req.get_full_url())[1]
@@ -624,7 +613,7 @@ class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
- header = 'Proxy-Authorization'
+ auth_header = 'Proxy-Authorization'
def http_error_407(self, req, fp, code, msg, headers):
host = req.get_host()
@@ -639,10 +628,9 @@ class AbstractDigestAuthHandler:
passwd = HTTPPasswordMgr()
self.passwd = passwd
self.add_password = self.passwd.add_password
- self.__current_realm = None
def http_error_auth_reqed(self, authreq, host, req, headers):
- authreq = headers.get(self.header, None)
+ authreq = headers.get(self.auth_header, None)
if authreq:
kind = authreq.split()[0]
if kind == 'Digest':
@@ -653,9 +641,11 @@ class AbstractDigestAuthHandler:
chal = parse_keqv_list(parse_http_list(challenge))
auth = self.get_authorization(req, chal)
if auth:
- req.add_header(self.header, 'Digest %s' % auth)
+ auth_val = 'Digest %s' % auth
+ if req.headers.get(self.auth_header, None) == auth_val:
+ return None
+ req.add_header(self.auth_header, auth_val)
resp = self.parent.open(req)
- self.__current_realm = None
return resp
def get_authorization(self, req, chal):
@@ -669,12 +659,6 @@ class AbstractDigestAuthHandler:
except KeyError:
return None
- if self.__current_realm is None:
- self.__current_realm = realm
- else:
- self.__current_realm = realm
- return None
-
H, KD = self.get_algorithm_impls(algorithm)
if H is None:
return None