diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-16 00:20:29 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-16 00:20:29 +0000 |
commit | 99d69350703593e50793dc6017cc67d31b54fe33 (patch) | |
tree | 6576111f7904b644fc3e547312f4ae9eef4872a0 /net/base | |
parent | 4066f2d8f1e778029f1663546d39efb221ffc590 (diff) | |
download | chromium_src-99d69350703593e50793dc6017cc67d31b54fe33.zip chromium_src-99d69350703593e50793dc6017cc67d31b54fe33.tar.gz chromium_src-99d69350703593e50793dc6017cc67d31b54fe33.tar.bz2 |
More correctly handle username and password in FtpNetworkTransaction.
- prevent newline injection attacks
- correctly unescape credentials provided in the URL
TEST=Covered by net_unittests.
http://crbug.com/20336
Review URL: http://codereview.chromium.org/183046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26305 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/net_error_list.h | 3 | ||||
-rw-r--r-- | net/base/net_util.cc | 8 | ||||
-rw-r--r-- | net/base/net_util.h | 6 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 65 |
4 files changed, 82 insertions, 0 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index c750295..745227e 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -257,6 +257,9 @@ NET_ERROR(PAC_SCRIPT_FAILED, -327) // satisfy the range requested. NET_ERROR(REQUEST_RANGE_NOT_SATISFIABLE, -328) +// The identity used for authentication is invalid. +NET_ERROR(MALFORMED_IDENTITY, -329) + // The cache does not have the requested entry. NET_ERROR(CACHE_MISS, -400) diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 5f6b548..b8c8add 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -1169,6 +1169,14 @@ std::string GetHostName() { return std::string(buffer); } +void GetIdentityFromURL(const GURL& url, + std::wstring* username, + std::wstring* password) { + UnescapeRule::Type flags = UnescapeRule::SPACES; + *username = UnescapeAndDecodeUTF8URLComponent(url.username(), flags); + *password = UnescapeAndDecodeUTF8URLComponent(url.password(), flags); +} + void AppendFormattedHost(const GURL& url, const std::wstring& languages, std::wstring* output, diff --git a/net/base/net_util.h b/net/base/net_util.h index 89386bf8..4d7e0aa 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -77,6 +77,12 @@ std::string NetAddressToString(const struct addrinfo* net_address); // Returns the hostname of the current system. Returns empty string on failure. std::string GetHostName(); +// Extracts the unescaped username/password from |url|, saving the results +// into |*username| and |*password|. +void GetIdentityFromURL(const GURL& url, + std::wstring* username, + std::wstring* password); + // Return the value of the HTTP response header with name 'name'. 'headers' // should be in the format that URLRequest::GetResponseHeaders() returns. // Returns the empty string if the header is not found. diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 2047b14..6a01ec9 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -530,6 +530,71 @@ TEST(NetUtilTest, FileURLConversion) { EXPECT_FALSE(net::FileURLToFilePath(GURL("filefoobar"), &output)); } +TEST(NetUtilTest, GetIdentityFromURL) { + 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", + }, + { // Keep %00 as is. + "http://use%00rname:password@google.com", + L"use%00rname", + 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; + net::GetIdentityFromURL(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(NetUtilTest, GetIdentityFromURL_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; + net::GetIdentityFromURL(url, &username, &password); + + // Verify that it was decoded as UTF8. + EXPECT_EQ(L"foo", username); + EXPECT_EQ(L"\x4f60\x597d", password); +} + // Just a bunch of fake headers. const wchar_t* google_headers = L"HTTP/1.1 200 OK\n" |