diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-14 01:00:29 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-14 01:00:29 +0000 |
commit | a97cca4ae68dc9f34ece5ff97de5675721cf88a1 (patch) | |
tree | 1b620640f855fb8ff2058b129132bb7d2a0cd3c8 /net | |
parent | 920894548dc271c46113b4960915f0d5bee5ceea (diff) | |
download | chromium_src-a97cca4ae68dc9f34ece5ff97de5675721cf88a1.zip chromium_src-a97cca4ae68dc9f34ece5ff97de5675721cf88a1.tar.gz chromium_src-a97cca4ae68dc9f34ece5ff97de5675721cf88a1.tar.bz2 |
Unescape username/passwords obtained from URLs before using them for HTTP auth.
BUG=http://crbug.com/19200
Review URL: http://codereview.chromium.org/164504
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23403 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_network_transaction.cc | 18 | ||||
-rw-r--r-- | net/http/http_network_transaction.h | 8 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 76 |
3 files changed, 95 insertions, 7 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index a3f5513..4b44cdc 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -1670,11 +1670,10 @@ bool HttpNetworkTransaction::SelectNextAuthIdentityToTry( auth_identity_[target].source == HttpAuth::IDENT_SRC_NONE) { auth_identity_[target].source = HttpAuth::IDENT_SRC_URL; auth_identity_[target].invalid = false; - // TODO(wtc) It may be necessary to unescape the username and password - // after extracting them from the URL. We should be careful about - // embedded nulls in that case. - auth_identity_[target].username = ASCIIToWide(request_->url.username()); - auth_identity_[target].password = ASCIIToWide(request_->url.password()); + // Extract the username:password from the URL. + GetIdentifyFromUrl(request_->url, + &auth_identity_[target].username, + &auth_identity_[target].password); // TODO(eroman): If the password is blank, should we also try combining // with a password from the cache? return true; @@ -1711,6 +1710,15 @@ bool HttpNetworkTransaction::SelectNextAuthIdentityToTry( return false; } +// static +void HttpNetworkTransaction::GetIdentifyFromUrl(const GURL& url, + std::wstring* username, + std::wstring* password) { + UnescapeRule::Type flags = UnescapeRule::SPACES; + *username = UnescapeAndDecodeUTF8URLComponent(url.username(), flags); + *password = UnescapeAndDecodeUTF8URLComponent(url.password(), flags); +} + std::string HttpNetworkTransaction::AuthChallengeLogMessage() const { std::string msg; std::string header_val; diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index 301aa92..5f489fc 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h @@ -62,6 +62,8 @@ class HttpNetworkTransaction : public HttpTransaction { private: FRIEND_TEST(HttpNetworkTransactionTest, ResetStateForRestart); + FRIEND_TEST(HttpNetworkTransactionTest, GetIdentifyFromUrl); + FRIEND_TEST(HttpNetworkTransactionTest, GetIdentifyFromUrl_UTF8); // This version of IOBuffer lets us use a string as the real storage and // "move" the data pointer inside the string before using it to do actual IO. @@ -259,6 +261,12 @@ class HttpNetworkTransaction : public HttpTransaction { // was found. bool SelectNextAuthIdentityToTry(HttpAuth::Target target); + // Extract the unescaped username/password from |url|, saving the results + // into |*username| and |*password|. + static void GetIdentifyFromUrl(const GURL& url, + std::wstring* username, + std::wstring* password); + // Searches the auth cache for an entry that encompasses the request's path. // If such an entry is found, updates auth_identity_[target] and // auth_handler_[target] with the cache entry's data and returns true. diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 05bb734..28465b3 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -2092,7 +2092,12 @@ TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) { HttpRequestInfo request; request.method = "GET"; // Note: the URL has a username:password in it. - request.url = GURL("http://foo:bar@www.google.com/"); + request.url = GURL("http://foo:b@r@www.google.com/"); + + // The password contains an escaped character -- for this test to pass it + // will need to be unescaped by HttpNetworkTransaction. + EXPECT_EQ("b%40r", request.url.password()); + request.load_flags = 0; MockWrite data_writes1[] = { @@ -2114,7 +2119,7 @@ TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) { MockWrite("GET / HTTP/1.1\r\n" "Host: www.google.com\r\n" "Connection: keep-alive\r\n" - "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), + "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"), }; MockRead data_reads2[] = { @@ -3508,4 +3513,71 @@ TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) { EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); } +TEST_F(HttpNetworkTransactionTest, GetIdentifyFromUrl) { + struct { + const char* input_url; + const wchar_t* expected_username; + const wchar_t* expected_password; + } tests[] = { + { + "http://username:password@google.com", + L"username", + L"password", + }, + { // Test for http://crbug.com/19200 + "http://username:p@ssword@google.com", + L"username", + L"p@ssword", + }, + { // Username contains %20. + "http://use rname:password@google.com", + L"use rname", + L"password", + }, + { // The URL canonicalizer for userinfo does not recognize non-ascii + // escapes it seems... So things like %00 will NOT be unescapable, + // since they are canonicalized by escaping the %... + "http://use%00rname:password@google.com", + L"use%2500rname", + L"password", + }, + { // Use a '+' in the username. + "http://use+rname:password@google.com", + L"use+rname", + L"password", + }, + { // Use a '&' in the password. + "http://username:p&ssword@google.com", + L"username", + L"p&ssword", + }, + }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + SCOPED_TRACE(StringPrintf("Test[%d]: %s", i, tests[i].input_url)); + GURL url(tests[i].input_url); + + std::wstring username, password; + HttpNetworkTransaction::GetIdentifyFromUrl(url, &username, &password); + + EXPECT_EQ(tests[i].expected_username, username); + EXPECT_EQ(tests[i].expected_password, password); + } +} + +// Try extracting a username which was encoded with UTF8. +TEST_F(HttpNetworkTransactionTest, GetIdentifyFromUrl_UTF8) { + GURL url(WideToUTF16(L"http://foo:\x4f60\x597d@blah.com")); + + EXPECT_EQ("foo", url.username()); + EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url.password()); + + // Extract the unescaped identity. + std::wstring username, password; + HttpNetworkTransaction::GetIdentifyFromUrl(url, &username, &password); + + // Verify that it was decoded as UTF8. + EXPECT_EQ(L"foo", username); + EXPECT_EQ(L"\x4f60\x597d", password); +} + } // namespace net |