diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-18 17:46:10 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-18 17:46:10 +0000 |
commit | 4de702f4d2053b586d4b9b12181ef953e2773da8 (patch) | |
tree | e7e60b480dce10b27ce51a04a6603332c31a395f /net/http | |
parent | 95c9bbd7141891389a00c3334df22be97ff37598 (diff) | |
download | chromium_src-4de702f4d2053b586d4b9b12181ef953e2773da8.zip chromium_src-4de702f4d2053b586d4b9b12181ef953e2773da8.tar.gz chromium_src-4de702f4d2053b586d4b9b12181ef953e2773da8.tar.bz2 |
We should pass the service principal name (SPN) of the
format "HTTP/host:port" as the third argument (pszTargetName)
to InitializeSecurityContext. This requires adding a
host_and_port parameter to some methods.
Remove obsolete (and incorrect) logging code in
HttpNetworkTransaction::PrepareForAuthRestart().
R=eroman
BUG=18009
TEST=none
Review URL: http://codereview.chromium.org/206022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26588 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_auth.cc | 8 | ||||
-rw-r--r-- | net/http/http_auth.h | 5 | ||||
-rw-r--r-- | net/http/http_auth_handler.cc | 4 | ||||
-rw-r--r-- | net/http/http_auth_handler.h | 9 | ||||
-rw-r--r-- | net/http/http_auth_handler_basic_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_auth_handler_digest_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_auth_handler_ntlm_win.cc | 11 | ||||
-rw-r--r-- | net/http/http_auth_unittest.cc | 10 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 50 |
9 files changed, 44 insertions, 59 deletions
diff --git a/net/http/http_auth.cc b/net/http/http_auth.cc index ce3e110..ba9b1ea 100644 --- a/net/http/http_auth.cc +++ b/net/http/http_auth.cc @@ -19,6 +19,7 @@ namespace net { // static void HttpAuth::ChooseBestChallenge(const HttpResponseHeaders* headers, Target target, + const GURL& origin, scoped_refptr<HttpAuthHandler>* handler) { // A connection-based authentication scheme must continue to use the // existing handler object in |*handler|. @@ -30,7 +31,7 @@ void HttpAuth::ChooseBestChallenge(const HttpResponseHeaders* headers, ChallengeTokenizer props(challenge.begin(), challenge.end()); if (LowerCaseEqualsASCII(props.scheme(), (*handler)->scheme().c_str()) && (*handler)->InitFromChallenge(challenge.begin(), challenge.end(), - target)) + target, origin)) return; } } @@ -42,7 +43,7 @@ void HttpAuth::ChooseBestChallenge(const HttpResponseHeaders* headers, void* iter = NULL; while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) { scoped_refptr<HttpAuthHandler> cur; - CreateAuthHandler(cur_challenge, target, &cur); + CreateAuthHandler(cur_challenge, target, origin, &cur); if (cur && (!best || best->score() < cur->score())) best.swap(cur); } @@ -52,6 +53,7 @@ void HttpAuth::ChooseBestChallenge(const HttpResponseHeaders* headers, // static void HttpAuth::CreateAuthHandler(const std::string& challenge, Target target, + const GURL& origin, scoped_refptr<HttpAuthHandler>* handler) { // Find the right auth handler for the challenge's scheme. ChallengeTokenizer props(challenge.begin(), challenge.end()); @@ -70,7 +72,7 @@ void HttpAuth::CreateAuthHandler(const std::string& challenge, } if (tmp_handler) { if (!tmp_handler->InitFromChallenge(challenge.begin(), challenge.end(), - target)) { + target, origin)) { // Invalid/unsupported challenge. tmp_handler = NULL; } diff --git a/net/http/http_auth.h b/net/http/http_auth.h index 5557694..38c9918 100644 --- a/net/http/http_auth.h +++ b/net/http/http_auth.h @@ -75,6 +75,7 @@ class HttpAuth { // |*handler| is set to NULL. static void CreateAuthHandler(const std::string& challenge, Target target, + const GURL& origin, scoped_refptr<HttpAuthHandler>* handler); // Iterate through the challenge headers, and pick the best one that @@ -84,11 +85,15 @@ class HttpAuth { // |*handler| is unchanged. If no supported challenge was found, |*handler| // is set to NULL. // + // |origin| is used by the NTLM authentication scheme to construct the + // service principal name. It is ignored by other schemes. + // // TODO(wtc): Continuing to use the existing handler in |*handler| (for // NTLM) is new behavior. Rename ChooseBestChallenge to fully encompass // what it does now. static void ChooseBestChallenge(const HttpResponseHeaders* headers, Target target, + const GURL& origin, scoped_refptr<HttpAuthHandler>* handler); // ChallengeTokenizer breaks up a challenge string into the the auth scheme diff --git a/net/http/http_auth_handler.cc b/net/http/http_auth_handler.cc index 6dac1f0..9abdd9a 100644 --- a/net/http/http_auth_handler.cc +++ b/net/http/http_auth_handler.cc @@ -9,7 +9,9 @@ namespace net { bool HttpAuthHandler::InitFromChallenge(std::string::const_iterator begin, std::string::const_iterator end, - HttpAuth::Target target) { + HttpAuth::Target target, + const GURL& origin) { + origin_ = origin; target_ = target; score_ = -1; properties_ = -1; diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h index 5ad96d2..1caf1a4 100644 --- a/net/http/http_auth_handler.h +++ b/net/http/http_auth_handler.h @@ -26,7 +26,8 @@ class HttpAuthHandler : public base::RefCounted<HttpAuthHandler> { // Initialize the handler by parsing a challenge string. bool InitFromChallenge(std::string::const_iterator begin, std::string::const_iterator end, - HttpAuth::Target target); + HttpAuth::Target target, + const GURL& origin); // Lowercase name of the auth scheme const std::string& scheme() const { @@ -94,9 +95,13 @@ class HttpAuthHandler : public base::RefCounted<HttpAuthHandler> { // The lowercase auth-scheme {"basic", "digest", "ntlm", ...} std::string scheme_; - // The realm. + // The realm. Used by "basic" and "digest". std::string realm_; + // The {scheme, host, port} for the authentication target. Used by "ntlm" + // to construct the service principal name. + GURL origin_; + // The score for this challenge. Higher numbers are better. int score_; diff --git a/net/http/http_auth_handler_basic_unittest.cc b/net/http/http_auth_handler_basic_unittest.cc index a6e4e3d..ca2004c 100644 --- a/net/http/http_auth_handler_basic_unittest.cc +++ b/net/http/http_auth_handler_basic_unittest.cc @@ -23,11 +23,12 @@ TEST(HttpAuthHandlerBasicTest, GenerateCredentials) { // Empty username and empty password. { L"", L"", "Basic Og==" }, }; + GURL origin("http://www.example.com"); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { std::string challenge = "Basic realm=\"Atlantis\""; scoped_refptr<HttpAuthHandlerBasic> basic = new HttpAuthHandlerBasic; basic->InitFromChallenge(challenge.begin(), challenge.end(), - HttpAuth::AUTH_SERVER); + HttpAuth::AUTH_SERVER, origin); std::string credentials = basic->GenerateCredentials(tests[i].username, tests[i].password, NULL, NULL); diff --git a/net/http/http_auth_handler_digest_unittest.cc b/net/http/http_auth_handler_digest_unittest.cc index c4abe26..5a27292 100644 --- a/net/http/http_auth_handler_digest_unittest.cc +++ b/net/http/http_auth_handler_digest_unittest.cc @@ -235,11 +235,12 @@ TEST(HttpAuthHandlerDigestTest, AssembleCredentials) { "qop=auth, nc=00000001, cnonce=\"15c07961ed8575c4\"" } }; + GURL origin("http://www.example.com"); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { scoped_refptr<HttpAuthHandlerDigest> digest = new HttpAuthHandlerDigest; std::string challenge = tests[i].challenge; EXPECT_TRUE(digest->InitFromChallenge( - challenge.begin(), challenge.end(), HttpAuth::AUTH_SERVER)); + challenge.begin(), challenge.end(), HttpAuth::AUTH_SERVER, origin)); std::string creds = digest->AssembleCredentials(tests[i].req_method, tests[i].req_path, tests[i].username, tests[i].password, diff --git a/net/http/http_auth_handler_ntlm_win.cc b/net/http/http_auth_handler_ntlm_win.cc index d638e8a..7970740 100644 --- a/net/http/http_auth_handler_ntlm_win.cc +++ b/net/http/http_auth_handler_ntlm_win.cc @@ -10,7 +10,9 @@ #include "net/http/http_auth_handler_ntlm.h" #include "base/logging.h" +#include "base/string_util.h" #include "net/base/net_errors.h" +#include "net/base/net_util.h" #pragma comment(lib, "secur32.lib") @@ -134,13 +136,16 @@ int HttpAuthHandlerNTLM::GetNextToken(const void* in_token, if (!out_buffer.pvBuffer) return ERR_OUT_OF_MEMORY; - // Name of the destination server. NULL for NTLM. - SEC_WCHAR* target = NULL; + // The service principal name of the destination server. See + // http://msdn.microsoft.com/en-us/library/ms677949%28VS.85%29.aspx + std::wstring target(L"HTTP/"); + target.append(ASCIIToWide(GetHostAndPort(origin_))); + wchar_t* target_name = const_cast<wchar_t*>(target.c_str()); // This returns a token that is passed to the remote server. status = InitializeSecurityContext(&cred_, // phCredential ctxt_ptr, // phContext - target, // pszTargetName + target_name, // pszTargetName 0, // fContextReq 0, // Reserved1 (must be 0) SECURITY_NATIVE_DREP, // TargetDataRep diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc index 9bd750e..bcd7472 100644 --- a/net/http/http_auth_unittest.cc +++ b/net/http/http_auth_unittest.cc @@ -48,6 +48,7 @@ TEST(HttpAuthTest, ChooseBestChallenge) { "", } }; + GURL origin("http://www.example.com"); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { // Make a HttpResponseHeaders object. @@ -62,6 +63,7 @@ TEST(HttpAuthTest, ChooseBestChallenge) { scoped_refptr<HttpAuthHandler> handler; HttpAuth::ChooseBestChallenge(headers.get(), HttpAuth::AUTH_SERVER, + origin, &handler); if (handler) { @@ -99,6 +101,7 @@ TEST(HttpAuthTest, ChooseBestChallengeConnectionBased) { "", } }; + GURL origin("http://www.example.com"); scoped_refptr<HttpAuthHandler> handler; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { @@ -114,6 +117,7 @@ TEST(HttpAuthTest, ChooseBestChallengeConnectionBased) { scoped_refptr<HttpAuthHandler> old_handler = handler; HttpAuth::ChooseBestChallenge(headers.get(), HttpAuth::AUTH_SERVER, + origin, &handler); EXPECT_TRUE(handler != NULL); @@ -229,10 +233,13 @@ TEST(HttpAuthTest, GetAuthorizationHeaderName) { } TEST(HttpAuthTest, CreateAuthHandler) { + GURL server_origin("http://www.example.com"); + GURL proxy_origin("http://cache.example.com:3128"); { scoped_refptr<HttpAuthHandler> handler; HttpAuth::CreateAuthHandler("Basic realm=\"FooBar\"", HttpAuth::AUTH_SERVER, + server_origin, &handler); EXPECT_FALSE(handler.get() == NULL); EXPECT_STREQ("basic", handler->scheme().c_str()); @@ -245,6 +252,7 @@ TEST(HttpAuthTest, CreateAuthHandler) { scoped_refptr<HttpAuthHandler> handler; HttpAuth::CreateAuthHandler("UNSUPPORTED realm=\"FooBar\"", HttpAuth::AUTH_SERVER, + server_origin, &handler); EXPECT_TRUE(handler.get() == NULL); } @@ -252,6 +260,7 @@ TEST(HttpAuthTest, CreateAuthHandler) { scoped_refptr<HttpAuthHandler> handler; HttpAuth::CreateAuthHandler("Digest realm=\"FooBar\", nonce=\"xyz\"", HttpAuth::AUTH_PROXY, + proxy_origin, &handler); EXPECT_FALSE(handler.get() == NULL); EXPECT_STREQ("digest", handler->scheme().c_str()); @@ -264,6 +273,7 @@ TEST(HttpAuthTest, CreateAuthHandler) { scoped_refptr<HttpAuthHandler> handler; HttpAuth::CreateAuthHandler("NTLM", HttpAuth::AUTH_SERVER, + server_origin, &handler); EXPECT_FALSE(handler.get() == NULL); EXPECT_STREQ("ntlm", handler->scheme().c_str()); diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 8fd0700..ad9de6a 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -283,45 +283,6 @@ void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) { // connection even though the server says it's keep-alive. } - // If the auth scheme is connection-based but the proxy/server mistakenly - // marks the connection as non-keep-alive, the auth is going to fail, so log - // an error message. - // - // TODO(wtc): has_auth_identity is not the right condition. We should - // be testing for "not round 1" here. See http://crbug.com/21015. - if (!keep_alive && auth_handler_[target]->is_connection_based() && - has_auth_identity) { - LOG(ERROR) << "Can't perform " << auth_handler_[target]->scheme() - << " auth to the " << AuthTargetString(target) << " " - << AuthOrigin(target) << " over a non-keep-alive connection"; - - HttpVersion http_version = response_.headers->GetHttpVersion(); - LOG(ERROR) << " HTTP version is " << http_version.major_value() << "." - << http_version.minor_value(); - - std::string header_val; - void* iter = NULL; - while (response_.headers->EnumerateHeader(&iter, "connection", - &header_val)) { - LOG(ERROR) << " Has header Connection: " << header_val; - } - - iter = NULL; - while (response_.headers->EnumerateHeader(&iter, "proxy-connection", - &header_val)) { - LOG(ERROR) << " Has header Proxy-Connection: " << header_val; - } - - // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate - // authentication with a "Proxy-Support: Session-Based-Authentication" - // response header. - iter = NULL; - while (response_.headers->EnumerateHeader(&iter, "proxy-support", - &header_val)) { - LOG(ERROR) << " Has header Proxy-Support: " << header_val; - } - } - // We don't need to drain the response body, so we act as if we had drained // the response body. DidDrainBodyForAuthRestart(keep_alive); @@ -1914,6 +1875,7 @@ int HttpNetworkTransaction::HandleAuthChallenge() { // Find the best authentication challenge that we support. HttpAuth::ChooseBestChallenge(response_.headers.get(), target, + AuthOrigin(target), &auth_handler_[target]); } @@ -1965,18 +1927,10 @@ void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target) { AuthChallengeInfo* auth_info = new AuthChallengeInfo; auth_info->is_proxy = target == HttpAuth::AUTH_PROXY; + auth_info->host_and_port = ASCIIToWide(GetHostAndPort(AuthOrigin(target))); auth_info->scheme = ASCIIToWide(auth_handler_[target]->scheme()); // TODO(eroman): decode realm according to RFC 2047. auth_info->realm = ASCIIToWide(auth_handler_[target]->realm()); - - std::string host_and_port; - if (target == HttpAuth::AUTH_PROXY) { - host_and_port = proxy_info_.proxy_server().host_and_port(); - } else { - DCHECK(target == HttpAuth::AUTH_SERVER); - host_and_port = GetHostAndPort(request_->url); - } - auth_info->host_and_port = ASCIIToWide(host_and_port); response_.auth_challenge = auth_info; } |