// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/http/http_auth.h" #include #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "net/base/net_errors.h" #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_auth_scheme.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" namespace net { HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {} // static void HttpAuth::ChooseBestChallenge( HttpAuthHandlerFactory* http_auth_handler_factory, const HttpResponseHeaders& response_headers, const SSLInfo& ssl_info, Target target, const GURL& origin, const std::set& disabled_schemes, const NetLogWithSource& net_log, std::unique_ptr* handler) { DCHECK(http_auth_handler_factory); DCHECK(handler->get() == NULL); // Choose the challenge whose authentication handler gives the maximum score. std::unique_ptr best; const std::string header_name = GetChallengeHeaderName(target); std::string cur_challenge; size_t iter = 0; while (response_headers.EnumerateHeader(&iter, header_name, &cur_challenge)) { std::unique_ptr cur; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( cur_challenge, target, ssl_info, origin, net_log, &cur); if (rv != OK) { VLOG(1) << "Unable to create AuthHandler. Status: " << ErrorToString(rv) << " Challenge: " << cur_challenge; continue; } if (cur.get() && (!best.get() || best->score() < cur->score()) && (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end())) best.swap(cur); } handler->swap(best); } // static HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse( HttpAuthHandler* handler, const HttpResponseHeaders& response_headers, Target target, const std::set& disabled_schemes, std::string* challenge_used) { DCHECK(handler); DCHECK(challenge_used); challenge_used->clear(); HttpAuth::Scheme current_scheme = handler->auth_scheme(); if (disabled_schemes.find(current_scheme) != disabled_schemes.end()) return HttpAuth::AUTHORIZATION_RESULT_REJECT; std::string current_scheme_name = SchemeToString(current_scheme); const std::string header_name = GetChallengeHeaderName(target); size_t iter = 0; std::string challenge; HttpAuth::AuthorizationResult authorization_result = HttpAuth::AUTHORIZATION_RESULT_INVALID; while (response_headers.EnumerateHeader(&iter, header_name, &challenge)) { HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); if (!base::LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str())) continue; authorization_result = handler->HandleAnotherChallenge(&props); if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) { *challenge_used = challenge; return authorization_result; } } // Finding no matches is equivalent to rejection. return HttpAuth::AUTHORIZATION_RESULT_REJECT; } // static std::string HttpAuth::GetChallengeHeaderName(Target target) { switch (target) { case AUTH_PROXY: return "Proxy-Authenticate"; case AUTH_SERVER: return "WWW-Authenticate"; default: NOTREACHED(); return std::string(); } } // static std::string HttpAuth::GetAuthorizationHeaderName(Target target) { switch (target) { case AUTH_PROXY: return HttpRequestHeaders::kProxyAuthorization; case AUTH_SERVER: return HttpRequestHeaders::kAuthorization; default: NOTREACHED(); return std::string(); } } // static std::string HttpAuth::GetAuthTargetString(Target target) { switch (target) { case AUTH_PROXY: return "proxy"; case AUTH_SERVER: return "server"; default: NOTREACHED(); return std::string(); } } // static const char* HttpAuth::SchemeToString(Scheme scheme) { static const char* const kSchemeNames[] = { kBasicAuthScheme, kDigestAuthScheme, kNtlmAuthScheme, kNegotiateAuthScheme, kSpdyProxyAuthScheme, kMockAuthScheme}; static_assert(arraysize(kSchemeNames) == AUTH_SCHEME_MAX, "http auth scheme names incorrect size"); if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) { NOTREACHED(); return "invalid_scheme"; } return kSchemeNames[scheme]; } } // namespace net