[Python-checkins] CVS: python/dist/src/Lib urllib2.py,1.23,1.24

Jeremy Hylton jhylton@users.sourceforge.net
Fri, 09 Nov 2001 08:46:53 -0800


Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv24845

Modified Files:
	urllib2.py 
Log Message:
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.


Index: urllib2.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/urllib2.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -d -r1.23 -r1.24
*** urllib2.py	2001/11/08 17:19:29	1.23
--- urllib2.py	2001/11/09 16:46:51	1.24
***************
*** 579,587 ****
          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):
--- 579,582 ----
***************
*** 596,619 ****
  
      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
          else:
-             self.__current_realm = None
              return None
  
  class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  
!     header = 'Authorization'
  
      def http_error_401(self, req, fp, code, msg, headers):
--- 591,608 ----
  
      def retry_http_basic_auth(self, host, req, realm):
          user,pw = self.passwd.find_user_password(realm, host)
          if pw:
              raw = "%s:%s" % (user, pw)
!             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:
              return None
  
  class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  
!     auth_header = 'Authorization'
  
      def http_error_401(self, req, fp, code, msg, headers):
***************
*** 625,629 ****
  class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  
!     header = 'Proxy-Authorization'
  
      def http_error_407(self, req, fp, code, msg, headers):
--- 614,618 ----
  class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  
!     auth_header = 'Proxy-Authorization'
  
      def http_error_407(self, req, fp, code, msg, headers):
***************
*** 640,647 ****
          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)
          if authreq:
              kind = authreq.split()[0]
--- 629,635 ----
          self.passwd = passwd
          self.add_password = self.passwd.add_password
  
      def http_error_auth_reqed(self, authreq, host, req, headers):
!         authreq = headers.get(self.auth_header, None)
          if authreq:
              kind = authreq.split()[0]
***************
*** 654,660 ****
          auth = self.get_authorization(req, chal)
          if auth:
!             req.add_header(self.header, 'Digest %s' % auth)
              resp = self.parent.open(req)
-             self.__current_realm = None
              return resp
  
--- 642,650 ----
          auth = self.get_authorization(req, chal)
          if 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)
              return resp
  
***************
*** 668,677 ****
              opaque = chal.get('opaque', None)
          except KeyError:
-             return None
- 
-         if self.__current_realm is None:
-             self.__current_realm = realm
-         else:
-             self.__current_realm = realm
              return None
  
--- 658,661 ----