Back to index

python3.2  3.2.2
Public Member Functions | Public Attributes | Static Public Attributes
urllib.request.HTTPDigestAuthHandler Class Reference
Inheritance diagram for urllib.request.HTTPDigestAuthHandler:
Inheritance graph
[legend]
Collaboration diagram for urllib.request.HTTPDigestAuthHandler:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def http_error_401
def add_parent
def close
def __lt__
def reset_retry_count
def http_error_auth_reqed
def retry_http_digest_auth
def get_cnonce
def get_authorization
def get_algorithm_impls
def get_entity_digest

Public Attributes

 parent
 passwd
 add_password
 retried
 nonce_count
 last_nonce

Static Public Attributes

string auth_header = 'Authorization'
int handler_order = 490

Detailed Description

An authentication protocol defined by RFC 2069

Digest authentication improves on basic authentication because it
does not transmit passwords in the clear.

Definition at line 1020 of file request.py.


Member Function Documentation

def urllib.request.BaseHandler.__lt__ (   self,
  other 
) [inherited]

Definition at line 467 of file request.py.

00467 
00468     def __lt__(self, other):
00469         if not hasattr(other, "handler_order"):
00470             # Try to preserve the old behavior of having custom classes
00471             # inserted after default ones (works only for custom user
00472             # classes which are not aware of handler_order).
00473             return True
00474         return self.handler_order < other.handler_order
00475 

def urllib.request.BaseHandler.add_parent (   self,
  parent 
) [inherited]

Definition at line 460 of file request.py.

00460 
00461     def add_parent(self, parent):
00462         self.parent = parent

def urllib.request.BaseHandler.close (   self) [inherited]

Definition at line 463 of file request.py.

00463 
00464     def close(self):
00465         # Only exists for backwards compatibility
00466         pass

Here is the caller graph for this function:

def urllib.request.AbstractDigestAuthHandler.get_algorithm_impls (   self,
  algorithm 
) [inherited]

Definition at line 1005 of file request.py.

01005 
01006     def get_algorithm_impls(self, algorithm):
01007         # lambdas assume digest modules are imported at the top level
01008         if algorithm == 'MD5':
01009             H = lambda x: hashlib.md5(x.encode("ascii")).hexdigest()
01010         elif algorithm == 'SHA':
01011             H = lambda x: hashlib.sha1(x.encode("ascii")).hexdigest()
01012         # XXX MD5-sess
01013         KD = lambda s, d: H("%s:%s" % (s, d))
01014         return H, KD

Here is the caller graph for this function:

def urllib.request.AbstractDigestAuthHandler.get_authorization (   self,
  req,
  chal 
) [inherited]

Definition at line 945 of file request.py.

00945 
00946     def get_authorization(self, req, chal):
00947         try:
00948             realm = chal['realm']
00949             nonce = chal['nonce']
00950             qop = chal.get('qop')
00951             algorithm = chal.get('algorithm', 'MD5')
00952             # mod_digest doesn't send an opaque, even though it isn't
00953             # supposed to be optional
00954             opaque = chal.get('opaque', None)
00955         except KeyError:
00956             return None
00957 
00958         H, KD = self.get_algorithm_impls(algorithm)
00959         if H is None:
00960             return None
00961 
00962         user, pw = self.passwd.find_user_password(realm, req.full_url)
00963         if user is None:
00964             return None
00965 
00966         # XXX not implemented yet
00967         if req.data is not None:
00968             entdig = self.get_entity_digest(req.data, chal)
00969         else:
00970             entdig = None
00971 
00972         A1 = "%s:%s:%s" % (user, realm, pw)
00973         A2 = "%s:%s" % (req.get_method(),
00974                         # XXX selector: what about proxies and full urls
00975                         req.selector)
00976         if qop == 'auth':
00977             if nonce == self.last_nonce:
00978                 self.nonce_count += 1
00979             else:
00980                 self.nonce_count = 1
00981                 self.last_nonce = nonce
00982             ncvalue = '%08x' % self.nonce_count
00983             cnonce = self.get_cnonce(nonce)
00984             noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, H(A2))
00985             respdig = KD(H(A1), noncebit)
00986         elif qop is None:
00987             respdig = KD(H(A1), "%s:%s" % (nonce, H(A2)))
00988         else:
00989             # XXX handle auth-int.
00990             raise URLError("qop '%s' is not supported." % qop)
00991 
00992         # XXX should the partial digests be encoded too?
00993 
00994         base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
00995                'response="%s"' % (user, realm, nonce, req.selector,
00996                                   respdig)
00997         if opaque:
00998             base += ', opaque="%s"' % opaque
00999         if entdig:
01000             base += ', digest="%s"' % entdig
01001         base += ', algorithm="%s"' % algorithm
01002         if qop:
01003             base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
01004         return base

Here is the call graph for this function:

Here is the caller graph for this function:

def urllib.request.AbstractDigestAuthHandler.get_cnonce (   self,
  nonce 
) [inherited]

Definition at line 934 of file request.py.

00934 
00935     def get_cnonce(self, nonce):
00936         # The cnonce-value is an opaque
00937         # quoted string value provided by the client and used by both client
00938         # and server to avoid chosen plaintext attacks, to provide mutual
00939         # authentication, and to provide some message integrity protection.
00940         # This isn't a fabulous effort, but it's probably Good Enough.
00941         s = "%s:%s:%s:" % (self.nonce_count, nonce, time.ctime())
00942         b = s.encode("ascii") + randombytes(8)
00943         dig = hashlib.sha1(b).hexdigest()
00944         return dig[:16]

Here is the call graph for this function:

Here is the caller graph for this function:

def urllib.request.AbstractDigestAuthHandler.get_entity_digest (   self,
  data,
  chal 
) [inherited]

Definition at line 1015 of file request.py.

01015 
01016     def get_entity_digest(self, data, chal):
01017         # XXX not implemented yet
01018         return None
01019 

Here is the caller graph for this function:

def urllib.request.HTTPDigestAuthHandler.http_error_401 (   self,
  req,
  fp,
  code,
  msg,
  headers 
)

Definition at line 1030 of file request.py.

01030 
01031     def http_error_401(self, req, fp, code, msg, headers):
01032         host = urlparse(req.full_url)[1]
01033         retry = self.http_error_auth_reqed('www-authenticate',
01034                                            host, req, headers)
01035         self.reset_retry_count()
01036         return retry
01037 

Here is the call graph for this function:

def urllib.request.AbstractDigestAuthHandler.http_error_auth_reqed (   self,
  auth_header,
  host,
  req,
  headers 
) [inherited]

Definition at line 905 of file request.py.

00905 
00906     def http_error_auth_reqed(self, auth_header, host, req, headers):
00907         authreq = headers.get(auth_header, None)
00908         if self.retried > 5:
00909             # Don't fail endlessly - if we failed once, we'll probably
00910             # fail a second time. Hm. Unless the Password Manager is
00911             # prompting for the information. Crap. This isn't great
00912             # but it's better than the current 'repeat until recursion
00913             # depth exceeded' approach <wink>
00914             raise HTTPError(req.full_url, 401, "digest auth failed",
00915                             headers, None)
00916         else:
00917             self.retried += 1
00918         if authreq:
00919             scheme = authreq.split()[0]
00920             if scheme.lower() == 'digest':
00921                 return self.retry_http_digest_auth(req, authreq)

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 902 of file request.py.

00902 
00903     def reset_retry_count(self):
00904         self.retried = 0

Here is the caller graph for this function:

def urllib.request.AbstractDigestAuthHandler.retry_http_digest_auth (   self,
  req,
  auth 
) [inherited]

Definition at line 922 of file request.py.

00922 
00923     def retry_http_digest_auth(self, req, auth):
00924         token, challenge = auth.split(' ', 1)
00925         chal = parse_keqv_list(filter(None, parse_http_list(challenge)))
00926         auth = self.get_authorization(req, chal)
00927         if auth:
00928             auth_val = 'Digest %s' % auth
00929             if req.headers.get(self.auth_header, None) == auth_val:
00930                 return None
00931             req.add_unredirected_header(self.auth_header, auth_val)
00932             resp = self.parent.open(req, timeout=req.timeout)
00933             return resp

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 897 of file request.py.

Definition at line 1027 of file request.py.

Reimplemented from urllib.request.BaseHandler.

Definition at line 1028 of file request.py.

Definition at line 900 of file request.py.

Definition at line 899 of file request.py.

Definition at line 461 of file request.py.

Definition at line 896 of file request.py.

Definition at line 898 of file request.py.


The documentation for this class was generated from the following file: