Fix closes Issue #11799: urllib.request Authentication Handlers will raise a

ValueError when presented with an unsupported Authentication Scheme.
This commit is contained in:
Senthil Kumaran 2011-05-11 21:17:57 +08:00
parent cc99528d87
commit 4de00a2e87
4 changed files with 63 additions and 16 deletions

View File

@ -240,10 +240,11 @@ The following classes are provided:
.. class:: HTTPBasicAuthHandler(password_mgr=None) .. class:: HTTPBasicAuthHandler(password_mgr=None)
Handle authentication with the remote host. *password_mgr*, if given, should be Handle authentication with the remote host. *password_mgr*, if given, should
something that is compatible with :class:`HTTPPasswordMgr`; refer to section be something that is compatible with :class:`HTTPPasswordMgr`; refer to
:ref:`http-password-mgr` for information on the interface that must be section :ref:`http-password-mgr` for information on the interface that must
supported. be supported. HTTPBasicAuthHandler will raise a :exc:`ValueError` when
presented with a wrong Authentication scheme.
.. class:: ProxyBasicAuthHandler(password_mgr=None) .. class:: ProxyBasicAuthHandler(password_mgr=None)
@ -265,10 +266,19 @@ The following classes are provided:
.. class:: HTTPDigestAuthHandler(password_mgr=None) .. class:: HTTPDigestAuthHandler(password_mgr=None)
Handle authentication with the remote host. *password_mgr*, if given, should be Handle authentication with the remote host. *password_mgr*, if given, should
something that is compatible with :class:`HTTPPasswordMgr`; refer to section be something that is compatible with :class:`HTTPPasswordMgr`; refer to
:ref:`http-password-mgr` for information on the interface that must be section :ref:`http-password-mgr` for information on the interface that must
supported. 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) .. class:: ProxyDigestAuthHandler(password_mgr=None)

View File

@ -5,6 +5,7 @@ import os
import io import io
import socket import socket
import array import array
import sys
import urllib.request import urllib.request
# The proxy bypass method imported below has logic specific to the OSX # 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_host(), "proxy.example.com:3128")
self.assertEqual(req.get_header("Proxy-authorization"),"FooBar") 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): def test_osx_proxy_bypass(self):
bypass = { bypass = {
'exclude_simple': False, 'exclude_simple': False,
@ -1265,6 +1268,26 @@ class HandlerTests(unittest.TestCase):
# _test_basic_auth called .open() twice) # _test_basic_auth called .open() twice)
self.assertEqual(opener.recorded, ["digest", "basic"]*2) 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, def _test_basic_auth(self, opener, auth_handler, auth_header,
realm, http_handler, password_manager, realm, http_handler, password_manager,
request_url, protected_url): request_url, protected_url):
@ -1302,6 +1325,7 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(len(http_handler.requests), 1) self.assertEqual(len(http_handler.requests), 1)
self.assertFalse(http_handler.requests[0].has_header(auth_header)) self.assertFalse(http_handler.requests[0].has_header(auth_header))
class MiscTests(unittest.TestCase): class MiscTests(unittest.TestCase):
def test_build_opener(self): def test_build_opener(self):

View File

@ -825,14 +825,20 @@ class AbstractBasicAuthHandler:
self.retried += 1 self.retried += 1
if authreq: if authreq:
mo = AbstractBasicAuthHandler.rx.search(authreq) scheme = authreq.split()[0]
if mo: if not scheme.lower() == 'basic':
scheme, quote, realm = mo.groups() raise ValueError("AbstractBasicAuthHandler does not"
if scheme.lower() == 'basic': " support the following scheme: '%s'" %
response = self.retry_http_basic_auth(host, req, realm) scheme)
if response and response.code != 401: else:
self.retried = 0 mo = AbstractBasicAuthHandler.rx.search(authreq)
return response 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): def retry_http_basic_auth(self, host, req, realm):
user, pw = self.passwd.find_user_password(realm, host) user, pw = self.passwd.find_user_password(realm, host)
@ -918,6 +924,9 @@ class AbstractDigestAuthHandler:
scheme = authreq.split()[0] scheme = authreq.split()[0]
if scheme.lower() == 'digest': if scheme.lower() == 'digest':
return self.retry_http_digest_auth(req, authreq) 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): def retry_http_digest_auth(self, req, auth):
token, challenge = auth.split(' ', 1) token, challenge = auth.split(' ', 1)

View File

@ -143,6 +143,10 @@ Core and Builtins
Library 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 - Issue #10419, #6011: build_scripts command of distutils handles correctly
non-ASCII path (path to the Python executable). Open and write the script in 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 binary mode, but ensure that the shebang is decodable from UTF-8 and from the