summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSenthil Kumaran <senthil@uthcode.com>2011-05-11 13:17:57 (GMT)
committerSenthil Kumaran <senthil@uthcode.com>2011-05-11 13:17:57 (GMT)
commit4de00a2e87ba7c69965ab4edcfcafc9eb63f0a97 (patch)
tree89f74bcd2b105eeaa6eedd4b8b36ddf379403a2b
parentcc99528d872e0f8a87a762a990beb9e3755cbb42 (diff)
downloadcpython-4de00a2e87ba7c69965ab4edcfcafc9eb63f0a97.zip
cpython-4de00a2e87ba7c69965ab4edcfcafc9eb63f0a97.tar.gz
cpython-4de00a2e87ba7c69965ab4edcfcafc9eb63f0a97.tar.bz2
Fix closes Issue #11799: urllib.request Authentication Handlers will raise a
ValueError when presented with an unsupported Authentication Scheme.
-rw-r--r--Doc/library/urllib.request.rst26
-rw-r--r--Lib/test/test_urllib2.py24
-rw-r--r--Lib/urllib/request.py25
-rw-r--r--Misc/NEWS4
4 files changed, 63 insertions, 16 deletions
diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst
index 3e24956..f99701d 100644
--- a/Doc/library/urllib.request.rst
+++ b/Doc/library/urllib.request.rst
@@ -240,10 +240,11 @@ The following classes are provided:
.. class:: HTTPBasicAuthHandler(password_mgr=None)
- Handle authentication with the remote host. *password_mgr*, if given, should be
- something that is compatible with :class:`HTTPPasswordMgr`; refer to section
- :ref:`http-password-mgr` for information on the interface that must be
- supported.
+ Handle authentication with the remote host. *password_mgr*, if given, should
+ be something that is compatible with :class:`HTTPPasswordMgr`; refer to
+ section :ref:`http-password-mgr` for information on the interface that must
+ be supported. HTTPBasicAuthHandler will raise a :exc:`ValueError` when
+ presented with a wrong Authentication scheme.
.. class:: ProxyBasicAuthHandler(password_mgr=None)
@@ -265,10 +266,19 @@ The following classes are provided:
.. class:: HTTPDigestAuthHandler(password_mgr=None)
- Handle authentication with the remote host. *password_mgr*, if given, should be
- something that is compatible with :class:`HTTPPasswordMgr`; refer to section
- :ref:`http-password-mgr` for information on the interface that must be
- supported.
+ Handle authentication with the remote host. *password_mgr*, if given, should
+ be something that is compatible with :class:`HTTPPasswordMgr`; refer to
+ section :ref:`http-password-mgr` for information on the interface that must
+ be supported. When both Digest Authentication Handler and Basic
+ Authentication Handler are both added, Digest Authentication is always tried
+ first. If the Digest Authentication returns a 40x response again, it is sent
+ to Basic Authentication handler to Handle. This Handler method will raise a
+ :exc:`ValueError` when presented with an authentication scheme other than
+ Digest or Basic.
+
+ ..versionchanged:: 3.3
+ Raise ValueError on unsupported Authentication Scheme.
+
.. class:: ProxyDigestAuthHandler(password_mgr=None)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index b6e4e91..8cd5ca0 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -5,6 +5,7 @@ import os
import io
import socket
import array
+import sys
import urllib.request
# The proxy bypass method imported below has logic specific to the OSX
@@ -1162,6 +1163,8 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(req.get_host(), "proxy.example.com:3128")
self.assertEqual(req.get_header("Proxy-authorization"),"FooBar")
+ # TODO: This should be only for OSX
+ @unittest.skipUnless(sys.platform == 'darwin', "only relevant for OSX")
def test_osx_proxy_bypass(self):
bypass = {
'exclude_simple': False,
@@ -1265,6 +1268,26 @@ class HandlerTests(unittest.TestCase):
# _test_basic_auth called .open() twice)
self.assertEqual(opener.recorded, ["digest", "basic"]*2)
+ def test_unsupported_auth_digest_handler(self):
+ opener = OpenerDirector()
+ # While using DigestAuthHandler
+ digest_auth_handler = urllib.request.HTTPDigestAuthHandler(None)
+ http_handler = MockHTTPHandler(
+ 401, 'WWW-Authenticate: Kerberos\r\n\r\n')
+ opener.add_handler(digest_auth_handler)
+ opener.add_handler(http_handler)
+ self.assertRaises(ValueError,opener.open,"http://www.example.com")
+
+ def test_unsupported_auth_basic_handler(self):
+ # While using BasicAuthHandler
+ opener = OpenerDirector()
+ basic_auth_handler = urllib.request.HTTPBasicAuthHandler(None)
+ http_handler = MockHTTPHandler(
+ 401, 'WWW-Authenticate: NTLM\r\n\r\n')
+ opener.add_handler(basic_auth_handler)
+ opener.add_handler(http_handler)
+ self.assertRaises(ValueError,opener.open,"http://www.example.com")
+
def _test_basic_auth(self, opener, auth_handler, auth_header,
realm, http_handler, password_manager,
request_url, protected_url):
@@ -1302,6 +1325,7 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(len(http_handler.requests), 1)
self.assertFalse(http_handler.requests[0].has_header(auth_header))
+
class MiscTests(unittest.TestCase):
def test_build_opener(self):
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index c80b7d1..e98a976 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -825,14 +825,20 @@ class AbstractBasicAuthHandler:
self.retried += 1
if authreq:
- mo = AbstractBasicAuthHandler.rx.search(authreq)
- if mo:
- scheme, quote, realm = mo.groups()
- if scheme.lower() == 'basic':
- response = self.retry_http_basic_auth(host, req, realm)
- if response and response.code != 401:
- self.retried = 0
- return response
+ scheme = authreq.split()[0]
+ if not scheme.lower() == 'basic':
+ raise ValueError("AbstractBasicAuthHandler does not"
+ " support the following scheme: '%s'" %
+ scheme)
+ else:
+ mo = AbstractBasicAuthHandler.rx.search(authreq)
+ if mo:
+ scheme, quote, realm = mo.groups()
+ if scheme.lower() == 'basic':
+ response = self.retry_http_basic_auth(host, req, realm)
+ if response and response.code != 401:
+ self.retried = 0
+ return response
def retry_http_basic_auth(self, host, req, realm):
user, pw = self.passwd.find_user_password(realm, host)
@@ -918,6 +924,9 @@ class AbstractDigestAuthHandler:
scheme = authreq.split()[0]
if scheme.lower() == 'digest':
return self.retry_http_digest_auth(req, authreq)
+ elif not scheme.lower() == 'basic':
+ raise ValueError("AbstractDigestAuthHandler does not support"
+ " the following scheme: '%s'" % scheme)
def retry_http_digest_auth(self, req, auth):
token, challenge = auth.split(' ', 1)
diff --git a/Misc/NEWS b/Misc/NEWS
index 7e4dd50..1e7d9ac 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -143,6 +143,10 @@ Core and Builtins
Library
-------
+- Issue #11799: urllib.request Authentication Handlers will raise a ValueError
+ when presented with an unsupported Authentication Scheme. Patch contributed
+ by Yuval Greenfield.
+
- Issue #10419, #6011: build_scripts command of distutils handles correctly
non-ASCII path (path to the Python executable). Open and write the script in
binary mode, but ensure that the shebang is decodable from UTF-8 and from the