aboutsummaryrefslogtreecommitdiff
path: root/requests/auth.py
diff options
context:
space:
mode:
authorSVN-Git Migration <python-modules-team@lists.alioth.debian.org>2015-10-08 13:41:31 -0700
committerSVN-Git Migration <python-modules-team@lists.alioth.debian.org>2015-10-08 13:41:31 -0700
commitca5cb993a3ce4fbdf50eebd31cb6b71eec9bc391 (patch)
tree0cb1e57a7e04660775dc9426c1e4476082f88d1d /requests/auth.py
parent224200a9815f792f93632d03a38e4f0763ae69ef (diff)
downloadpython-requests-ca5cb993a3ce4fbdf50eebd31cb6b71eec9bc391.tar
python-requests-ca5cb993a3ce4fbdf50eebd31cb6b71eec9bc391.tar.gz
Imported Upstream version 2.2.1
Diffstat (limited to 'requests/auth.py')
-rw-r--r--requests/auth.py54
1 files changed, 35 insertions, 19 deletions
diff --git a/requests/auth.py b/requests/auth.py
index 30529e2..6664cd8 100644
--- a/requests/auth.py
+++ b/requests/auth.py
@@ -16,6 +16,7 @@ import logging
from base64 import b64encode
from .compat import urlparse, str
+from .cookies import extract_cookies_to_jar
from .utils import parse_dict_header
log = logging.getLogger(__name__)
@@ -63,6 +64,7 @@ class HTTPDigestAuth(AuthBase):
self.last_nonce = ''
self.nonce_count = 0
self.chal = {}
+ self.pos = None
def build_digest_header(self, method, url):
@@ -77,7 +79,7 @@ class HTTPDigestAuth(AuthBase):
else:
_algorithm = algorithm.upper()
# lambdas assume digest modules are imported at the top level
- if _algorithm == 'MD5':
+ if _algorithm == 'MD5' or _algorithm == 'MD5-SESS':
def md5_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
@@ -89,7 +91,7 @@ class HTTPDigestAuth(AuthBase):
x = x.encode('utf-8')
return hashlib.sha1(x).hexdigest()
hash_utf8 = sha_utf8
- # XXX MD5-sess
+
KD = lambda s, d: hash_utf8("%s:%s" % (s, d))
if hash_utf8 is None:
@@ -105,23 +107,28 @@ class HTTPDigestAuth(AuthBase):
A1 = '%s:%s:%s' % (self.username, realm, self.password)
A2 = '%s:%s' % (method, path)
+ HA1 = hash_utf8(A1)
+ HA2 = hash_utf8(A2)
+
+ if nonce == self.last_nonce:
+ self.nonce_count += 1
+ else:
+ self.nonce_count = 1
+ ncvalue = '%08x' % self.nonce_count
+ s = str(self.nonce_count).encode('utf-8')
+ s += nonce.encode('utf-8')
+ s += time.ctime().encode('utf-8')
+ s += os.urandom(8)
+
+ cnonce = (hashlib.sha1(s).hexdigest()[:16])
+ noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, HA2)
+ if _algorithm == 'MD5-SESS':
+ HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce))
+
if qop is None:
- respdig = KD(hash_utf8(A1), "%s:%s" % (nonce, hash_utf8(A2)))
+ respdig = KD(HA1, "%s:%s" % (nonce, HA2))
elif qop == 'auth' or 'auth' in qop.split(','):
- if nonce == self.last_nonce:
- self.nonce_count += 1
- else:
- self.nonce_count = 1
-
- ncvalue = '%08x' % self.nonce_count
- s = str(self.nonce_count).encode('utf-8')
- s += nonce.encode('utf-8')
- s += time.ctime().encode('utf-8')
- s += os.urandom(8)
-
- cnonce = (hashlib.sha1(s).hexdigest()[:16])
- noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, hash_utf8(A2))
- respdig = KD(hash_utf8(A1), noncebit)
+ respdig = KD(HA1, noncebit)
else:
# XXX handle auth-int.
return None
@@ -138,13 +145,17 @@ class HTTPDigestAuth(AuthBase):
if entdig:
base += ', digest="%s"' % entdig
if qop:
- base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
+ base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce)
return 'Digest %s' % (base)
def handle_401(self, r, **kwargs):
"""Takes the given response and tries digest-auth, if needed."""
+ if self.pos is not None:
+ # Rewind the file position indicator of the body to where
+ # it was to resend the request.
+ r.request.body.seek(self.pos)
num_401_calls = getattr(self, 'num_401_calls', 1)
s_auth = r.headers.get('www-authenticate', '')
@@ -159,7 +170,8 @@ class HTTPDigestAuth(AuthBase):
r.content
r.raw.release_conn()
prep = r.request.copy()
- prep.prepare_cookies(r.cookies)
+ extract_cookies_to_jar(prep._cookies, r.request, r.raw)
+ prep.prepare_cookies(prep._cookies)
prep.headers['Authorization'] = self.build_digest_header(
prep.method, prep.url)
@@ -176,5 +188,9 @@ class HTTPDigestAuth(AuthBase):
# If we have a saved nonce, skip the 401
if self.last_nonce:
r.headers['Authorization'] = self.build_digest_header(r.method, r.url)
+ try:
+ self.pos = r.body.tell()
+ except AttributeError:
+ pass
r.register_hook('response', self.handle_401)
return r