summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-03-02 05:50:32 -0800
committerGitHub <noreply@github.com>2022-03-02 14:50:32 +0100
commit1c9701a3de0566c085e03dddc14a8508aaae349e (patch)
tree5c193ab56d3e54be17b494088101df6bb99da02e
parenteb6c840a2414dc057ffcfbb5ad68d6253c8dd57c (diff)
downloadcpython-git-1c9701a3de0566c085e03dddc14a8508aaae349e.tar.gz
bpo-46756: Fix authorization check in urllib.request (GH-31353) (GH-31572)
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". (cherry picked from commit e2e72567a1c94c548868f6ee5329363e6036057a) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r--Lib/test/test_urllib2.py25
-rw-r--r--Lib/urllib/request.py8
-rw-r--r--Misc/NEWS.d/next/Library/2022-02-15-11-57-53.bpo-46756.AigSPi.rst5
3 files changed, 30 insertions, 8 deletions
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index b77f90a6cc..b61a40cfd3 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -158,7 +158,6 @@ class RequestHdrsTests(unittest.TestCase):
self.assertEqual(find_user_pass("Some Realm",
"http://example.com/spam"),
('joe', 'password'))
-
self.assertEqual(find_user_pass("Some Realm",
"http://example.com/spam/spam"),
('joe', 'password'))
@@ -167,12 +166,29 @@ class RequestHdrsTests(unittest.TestCase):
add("c", "http://example.com/foo", "foo", "ni")
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"),
('foo', 'ni'))
-
self.assertEqual(find_user_pass("c", "http://example.com/bar"),
('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.
@@ -1653,8 +1669,9 @@ class HandlerTests(unittest.TestCase):
auth_prior_handler.add_password(
None, request_url, user, password, is_authenticated=True)
- is_auth = pwd_manager.is_authenticated(request_url)
- self.assertTrue(is_auth)
+ self.assertTrue(pwd_manager.is_authenticated(request_url))
+ self.assertTrue(pwd_manager.is_authenticated(request_url + '/nested'))
+ self.assertFalse(pwd_manager.is_authenticated(request_url + 'plain'))
opener = OpenerDirector()
opener.add_handler(auth_prior_handler)
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index 5f67077fb0..8ff5e3e24a 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -895,10 +895,10 @@ class HTTPPasswordMgr:
return True
if base[0] != test[0]:
return False
- common = posixpath.commonprefix((base[1], test[1]))
- if len(common) == len(base[1]):
- return True
- return False
+ prefix = base[1]
+ if prefix[-1:] != '/':
+ prefix += '/'
+ return test[1].startswith(prefix)
class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr):
diff --git a/Misc/NEWS.d/next/Library/2022-02-15-11-57-53.bpo-46756.AigSPi.rst b/Misc/NEWS.d/next/Library/2022-02-15-11-57-53.bpo-46756.AigSPi.rst
new file mode 100644
index 0000000000..1660640c5d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-02-15-11-57-53.bpo-46756.AigSPi.rst
@@ -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``.