summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-14 01:00:29 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-14 01:00:29 +0000
commita97cca4ae68dc9f34ece5ff97de5675721cf88a1 (patch)
tree1b620640f855fb8ff2058b129132bb7d2a0cd3c8 /net
parent920894548dc271c46113b4960915f0d5bee5ceea (diff)
downloadchromium_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.cc18
-rw-r--r--net/http/http_network_transaction.h8
-rw-r--r--net/http/http_network_transaction_unittest.cc76
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