mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
bpo-46756: Fix authorization check in urllib.request (GH-31353)
Fix a bug in urllib.request.HTTPPasswordMgr.find_user_password() and urllib.request.HTTPPasswordMgrWithPriorAuth.is_authenticated() which allowed to bypass authorization. For example, access to URI "example.org/foobar" was allowed if the user was authorized for URI "example.org/foo".
This commit is contained in:
parent
53ecf9e08d
commit
e2e72567a1
3 changed files with 30 additions and 8 deletions
|
@ -164,7 +164,6 @@ class RequestHdrsTests(unittest.TestCase):
|
||||||
self.assertEqual(find_user_pass("Some Realm",
|
self.assertEqual(find_user_pass("Some Realm",
|
||||||
"http://example.com/spam"),
|
"http://example.com/spam"),
|
||||||
('joe', 'password'))
|
('joe', 'password'))
|
||||||
|
|
||||||
self.assertEqual(find_user_pass("Some Realm",
|
self.assertEqual(find_user_pass("Some Realm",
|
||||||
"http://example.com/spam/spam"),
|
"http://example.com/spam/spam"),
|
||||||
('joe', 'password'))
|
('joe', 'password'))
|
||||||
|
@ -173,12 +172,29 @@ class RequestHdrsTests(unittest.TestCase):
|
||||||
|
|
||||||
add("c", "http://example.com/foo", "foo", "ni")
|
add("c", "http://example.com/foo", "foo", "ni")
|
||||||
add("c", "http://example.com/bar", "bar", "nini")
|
add("c", "http://example.com/bar", "bar", "nini")
|
||||||
|
add("c", "http://example.com/foo/bar", "foobar", "nibar")
|
||||||
|
|
||||||
self.assertEqual(find_user_pass("c", "http://example.com/foo"),
|
self.assertEqual(find_user_pass("c", "http://example.com/foo"),
|
||||||
('foo', 'ni'))
|
('foo', 'ni'))
|
||||||
|
|
||||||
self.assertEqual(find_user_pass("c", "http://example.com/bar"),
|
self.assertEqual(find_user_pass("c", "http://example.com/bar"),
|
||||||
('bar', 'nini'))
|
('bar', 'nini'))
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/foo/"),
|
||||||
|
('foo', 'ni'))
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/foo/bar"),
|
||||||
|
('foo', 'ni'))
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/foo/baz"),
|
||||||
|
('foo', 'ni'))
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/foobar"),
|
||||||
|
(None, None))
|
||||||
|
|
||||||
|
add("c", "http://example.com/baz/", "baz", "ninini")
|
||||||
|
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/baz"),
|
||||||
|
(None, None))
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/baz/"),
|
||||||
|
('baz', 'ninini'))
|
||||||
|
self.assertEqual(find_user_pass("c", "http://example.com/baz/bar"),
|
||||||
|
('baz', 'ninini'))
|
||||||
|
|
||||||
# For the same path, newer password should be considered.
|
# For the same path, newer password should be considered.
|
||||||
|
|
||||||
|
@ -1658,8 +1674,9 @@ class HandlerTests(unittest.TestCase):
|
||||||
auth_prior_handler.add_password(
|
auth_prior_handler.add_password(
|
||||||
None, request_url, user, password, is_authenticated=True)
|
None, request_url, user, password, is_authenticated=True)
|
||||||
|
|
||||||
is_auth = pwd_manager.is_authenticated(request_url)
|
self.assertTrue(pwd_manager.is_authenticated(request_url))
|
||||||
self.assertTrue(is_auth)
|
self.assertTrue(pwd_manager.is_authenticated(request_url + '/nested'))
|
||||||
|
self.assertFalse(pwd_manager.is_authenticated(request_url + 'plain'))
|
||||||
|
|
||||||
opener = OpenerDirector()
|
opener = OpenerDirector()
|
||||||
opener.add_handler(auth_prior_handler)
|
opener.add_handler(auth_prior_handler)
|
||||||
|
|
|
@ -889,10 +889,10 @@ class HTTPPasswordMgr:
|
||||||
return True
|
return True
|
||||||
if base[0] != test[0]:
|
if base[0] != test[0]:
|
||||||
return False
|
return False
|
||||||
common = posixpath.commonprefix((base[1], test[1]))
|
prefix = base[1]
|
||||||
if len(common) == len(base[1]):
|
if prefix[-1:] != '/':
|
||||||
return True
|
prefix += '/'
|
||||||
return False
|
return test[1].startswith(prefix)
|
||||||
|
|
||||||
|
|
||||||
class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr):
|
class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr):
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Fix a bug in :meth:`urllib.request.HTTPPasswordMgr.find_user_password` and
|
||||||
|
:meth:`urllib.request.HTTPPasswordMgrWithPriorAuth.is_authenticated` which
|
||||||
|
allowed to bypass authorization. For example, access to URI
|
||||||
|
``example.org/foobar`` was allowed if the user was authorized for URI
|
||||||
|
``example.org/foo``.
|
Loading…
Add table
Add a link
Reference in a new issue