@@ -1789,6 +1789,31 @@ def test_proxy_digest_auth(self):
17891789 http_handler .requests [1 ]
17901790 .get_header ("Proxy-authorization" ).startswith ("Digest " ))
17911791
1792+ def test_proxy_digest_auth_uri (self ):
1793+ # The digest-uri of a request sent through an HTTP proxy is the
1794+ # absolute URL, matching the absolute-form request line
1795+ opener = OpenerDirector ()
1796+ ph = urllib .request .ProxyHandler (dict (http = "proxy.example.com:3128" ))
1797+ opener .add_handler (ph )
1798+ password_manager = urllib .request .HTTPPasswordMgr ()
1799+ digest_handler = urllib .request .ProxyDigestAuthHandler (password_manager )
1800+ realm = "ACME Networks"
1801+ http_handler = MockHTTPHandlerRedirect (
1802+ 407 ,
1803+ 'Proxy-Authenticate: Digest realm="%s", nonce="abcdef0123456789", '
1804+ 'algorithm="SHA-256"\r \n \r \n ' % realm )
1805+ opener .add_handler (digest_handler )
1806+ opener .add_handler (http_handler )
1807+
1808+ request_url = "http://acme.example.com/protected"
1809+ digest_handler .add_password (realm , "proxy.example.com:3128" ,
1810+ "wile" , "coyote" )
1811+ opener .open (request_url )
1812+
1813+ self .assertEqual (len (http_handler .requests ), 2 )
1814+ auth = http_handler .requests [1 ].get_header ("Proxy-authorization" )
1815+ self .assertIn ('uri="%s"' % request_url , auth )
1816+
17921817 def test_digest_auth_uses_full_url (self ):
17931818 # The non-proxy case must keep using the full request URL (not
17941819 # just the host) for the password lookup, so that sub-URI realm
@@ -1811,6 +1836,26 @@ def test_digest_auth_uses_full_url(self):
18111836 self .assertEqual (password_manager .target_realm , realm )
18121837 self .assertEqual (password_manager .target_url , request_url )
18131838
1839+ def test_digest_auth_empty_path (self ):
1840+ # gh-53089: the digest-uri must match the Request-URI, which is
1841+ # '/' for a URL with an empty path
1842+ password_manager = urllib .request .HTTPPasswordMgr ()
1843+ digest_handler = urllib .request .HTTPDigestAuthHandler (password_manager )
1844+ realm = "ACME Networks"
1845+ digest_handler .add_password (realm , "http://acme.example.com" ,
1846+ "wile" , "coyote" )
1847+ req = Request ("http://acme.example.com" )
1848+ chal = {"realm" : realm , "nonce" : "abcdef0123456789" ,
1849+ "algorithm" : "SHA-256" }
1850+
1851+ auth = digest_handler .get_authorization (req , chal )
1852+
1853+ H , KD = digest_handler .get_algorithm_impls ("SHA-256" )
1854+ respdig = KD (H ("wile:%s:coyote" % realm ),
1855+ "abcdef0123456789:%s" % H ("GET:/" ))
1856+ self .assertIn ('uri="/"' , auth )
1857+ self .assertIn ('response="%s"' % respdig , auth )
1858+
18141859 def test_basic_and_digest_auth_handlers (self ):
18151860 # HTTPDigestAuthHandler raised an exception if it couldn't handle a 40*
18161861 # response (https://bugs.python.org/issue1479302), where it should instead
0 commit comments