From 649dac1029ad51e01091a06feac81f199249cfc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=90=E8=97=A4=20=E5=BB=BA=E5=A4=AA?= Date: Fri, 29 Nov 2013 15:28:47 +0900 Subject: [PATCH 1/2] quote qop options in Digest Auth Based on RFC2617 (http://tools.ietf.org/html/rfc2617), the value of 'qop-options' directive should be quoted with double quotes: qop-options This directive is optional, but is made so only for backward compatibility with RFC 2069 [6]; it SHOULD be used by all implementations compliant with this version of the Digest scheme. If present, it is a quoted string of one or more tokens indicating the "quality of protection" values supported by the server. The value "auth" indicates authentication; the value "auth-int" indicates authentication with integrity protection; see the curl comamnd-line tool also appends these quotes. You can see this by `curl -v --digest --user user:passwd http://example.com/digest-auth`. Unfortunately, some minor server-side implementations seem to be sensitive on this difference. --- requests/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requests/auth.py b/requests/auth.py index a3de123d..48416e5f 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -144,7 +144,7 @@ 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) From fecb35a08ec77d6392bdc609ab1ea21943e40228 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Fri, 29 Nov 2013 08:37:25 +0000 Subject: [PATCH 2/2] Quote qop values in digest auth. --- requests/auth.py | 4 ++-- test_requests.py | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/requests/auth.py b/requests/auth.py index a3de123d..f87087df 100644 --- a/requests/auth.py +++ b/requests/auth.py @@ -105,7 +105,7 @@ 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) @@ -144,7 +144,7 @@ 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) diff --git a/test_requests.py b/test_requests.py index 3b673956..4035695d 100755 --- a/test_requests.py +++ b/test_requests.py @@ -320,6 +320,14 @@ class RequestsTestCase(unittest.TestCase): r = s.get(url) assert r.status_code == 401 + def test_DIGESTAUTH_QUOTES_QOP_VALUE(self): + + auth = HTTPDigestAuth('user', 'pass') + url = httpbin('digest-auth', 'auth', 'user', 'pass') + + r = requests.get(url, auth=auth) + assert '"auth"' in r.request.headers['Authorization'] + def test_POSTBIN_GET_POST_FILES(self): url = httpbin('post')