Rev 2434: Tested against squid-2.6.5 with digest authentication. in http://bazaar.launchpad.net/~bzr/bzr/bzr.http.auth
Vincent Ladeuil
v.ladeuil+lp at free.fr
Sun Apr 22 11:01:34 BST 2007
At http://bazaar.launchpad.net/~bzr/bzr/bzr.http.auth
------------------------------------------------------------
revno: 2434
revision-id: v.ladeuil+lp at free.fr-20070422100132-98l662vmscalaiin
parent: v.ladeuil+lp at free.fr-20070421213132-6ffsjiv1bf6tnfhq
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: bzr.http.auth
timestamp: Sun 2007-04-22 12:01:32 +0200
message:
Tested against squid-2.6.5 with digest authentication.
* bzrlib/transport/http/_urllib2_wrappers.py:
(DigestAuthHandler.build_auth_header): Only the request path
should appear in the uri. nc value should not be quoted for
squid (the devil is in the details...). Well, some cleaning
helped. Don't put algorithm in the header if none was specified by
the server.
modified:
bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
-------------- next part --------------
=== modified file 'bzrlib/transport/http/_urllib2_wrappers.py'
--- a/bzrlib/transport/http/_urllib2_wrappers.py 2007-04-21 21:29:34 +0000
+++ b/bzrlib/transport/http/_urllib2_wrappers.py 2007-04-22 10:01:32 +0000
@@ -918,13 +918,14 @@
def auth_params_reusable(self, auth):
# If the auth scheme is known, it means a previous
- # authentication was succesful, all information is
+ # authentication was successful, all information is
# available, no further checks are needed.
return auth.get('scheme', None) == 'basic'
def get_digest_algorithm_impls(algorithm):
H = None
+ KD = None
if algorithm == 'MD5':
H = lambda x: md5.new(x).hexdigest()
elif algorithm == 'SHA':
@@ -934,12 +935,18 @@
return H, KD
+def get_new_cnonce(nonce, nonce_count):
+ raw = '%s:%d:%s:%s' % (nonce, nonce_count, time.ctime(),
+ urllib2.randombytes(8))
+ return sha.new(raw).hexdigest()[:16]
+
+
class DigestAuthHandler(AbstractAuthHandler):
"""A custom digest authentication handler."""
def auth_params_reusable(self, auth):
# If the auth scheme is known, it means a previous
- # authentication was succesful, all information is
+ # authentication was successful, all information is
# available, no further checks are needed.
return auth.get('scheme', None) == 'digest'
@@ -963,8 +970,7 @@
# We already tried that
return False
- algorithm = req_auth.get('algorithm', 'MD5')
- H, KD = get_digest_algorithm_impls(algorithm)
+ H, KD = get_digest_algorithm_impls(req_auth.get('algorithm', 'MD5'))
if H is None:
return False
@@ -976,43 +982,51 @@
# Put useful info into auth
try:
auth['scheme'] = scheme
- auth['algorithm'] = algorithm
+ if req_auth.get('algorithm', None) is not None:
+ auth['algorithm'] = req_auth.get('algorithm')
auth['realm'] = req_auth['realm']
auth['nonce'] = req_auth['nonce']
auth['qop'] = qop
auth['opaque'] = req_auth.get('opaque', None)
except KeyError:
+ # Some required field is not there
return False
return True
def build_auth_header(self, auth, request):
- uri = request.get_selector()
+ url_scheme, url_selector = urllib.splittype(request.get_selector())
+ sel_host, uri = urllib.splithost(url_selector)
+
A1 = '%s:%s:%s' % (auth['user'], auth['realm'], auth['password'])
A2 = '%s:%s' % (request.get_method(), uri)
+
nonce = auth['nonce']
qop = auth['qop']
- H, KD = get_digest_algorithm_impls(auth['algorithm'])
nonce_count = auth.get('nonce_count',0)
nonce_count += 1
ncvalue = '%08x' % nonce_count
- cnonce = sha.new("%s:%s:%s:%s" % (nonce_count, nonce,
- time.ctime(), urllib2.randombytes(8))
- ).hexdigest()[:16]
- noncebit = '%s:%s:%s:%s:%s' % (nonce, ncvalue, cnonce, qop, H(A2))
- response_digest = KD(H(A1), noncebit)
+ cnonce = get_new_cnonce(nonce, nonce_count)
+
+ H, KD = get_digest_algorithm_impls(auth.get('algorithm', 'MD5'))
+ nonce_data = '%s:%s:%s:%s:%s' % (nonce, ncvalue, cnonce, qop, H(A2))
+ request_digest = KD(H(A1), nonce_data)
header = 'Digest '
- header += 'username="%s", realm="%s", nonce="%s",' % (auth['user'],
+ header += 'username="%s", realm="%s", nonce="%s"' % (auth['user'],
auth['realm'],
nonce)
- header += ' uri="%s", response="%s"' % (uri, response_digest)
+ header += ', uri="%s"' % uri
+ header += ', cnonce="%s", nc=%s' % (cnonce, ncvalue)
+ header += ', qop="%s"' % qop
+ header += ', response="%s"' % request_digest
+ # Append the optional fields
opaque = auth.get('opaque', None)
if opaque:
header += ', opaque="%s"' % opaque
- header += ', algorithm="%s"' % auth['algorithm']
- header += ', qop="%s", nc="%s", cnonce="%s"' % (qop, ncvalue, cnonce)
+ if auth.get('algorithm', None):
+ header += ', algorithm="%s"' % auth.get('algorithm')
# We have used the nonce once more, update the count
auth['nonce_count'] = nonce_count
More information about the bazaar-commits
mailing list