Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(747)

Unified Diff: net/http/http_auth.cc

Issue 1157333005: [net/http auth] Use strings to identify authentication schemes. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_auth.h ('k') | net/http/http_auth_cache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_auth.cc
diff --git a/net/http/http_auth.cc b/net/http/http_auth.cc
index 7752d743a22a356ea659577e858ad8aa3f2c017b..28fa76b006123a9de1d6464641956b99e34914e0 100644
--- a/net/http/http_auth.cc
+++ b/net/http/http_auth.cc
@@ -7,49 +7,120 @@
#include <algorithm>
#include "base/basictypes.h"
+#include "base/bind.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
+#include "base/values.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_set.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
namespace net {
+namespace {
+
+// Hardcoded map of HTTP authentication scheme priorities. Higher priorities are
+// preferred over lower.
+struct SchemePriority {
+ const char* scheme;
+ int priority;
+} kSchemeScores[] = {
+ {"basic", 1},
+ {"digest", 2},
+ {"ntlm", 3},
+ {"negotiate", 4},
+};
+
+// Priority assigned to unknown authentication schemes. They are currently
+// ranked lower than Basic, which might be a bit too conservative.
+const int kSchemePriorityDefault = 0;
+
+// Not a valid priority.
+const int kSchemePriorityInvalid = -1;
+
+// Higher priority schemes are preferred over lower priority schemes.
+int GetSchemePriority(const std::string& scheme) {
+ DCHECK(HttpAuth::IsValidNormalizedScheme(scheme));
+ for (const auto& iter : kSchemeScores) {
+ if (scheme == iter.scheme)
+ return iter.priority;
+ }
+ return kSchemePriorityDefault;
+}
+
+scoped_ptr<base::Value> AuthHandlerCreationFailureParams(
+ const std::string* challenge,
+ int error,
+ NetLogCaptureMode capture_mode) {
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->SetString("challenge", *challenge);
+ dict->SetInteger("net_error", error);
+ return dict.Pass();
+}
+
+} // namespace
+
HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {}
+HttpAuth::Identity::~Identity() {}
+
// static
void HttpAuth::ChooseBestChallenge(
HttpAuthHandlerFactory* http_auth_handler_factory,
const HttpResponseHeaders* headers,
Target target,
const GURL& origin,
- const std::set<Scheme>& disabled_schemes,
+ const HttpAuthSchemeSet& disabled_schemes,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
DCHECK(http_auth_handler_factory);
- DCHECK(handler->get() == NULL);
+ DCHECK(!handler->get());
- // Choose the challenge whose authentication handler gives the maximum score.
+ int best_priority = kSchemePriorityInvalid;
scoped_ptr<HttpAuthHandler> best;
const std::string header_name = GetChallengeHeaderName(target);
std::string cur_challenge;
- void* iter = NULL;
+ void* iter = nullptr;
+
while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) {
- scoped_ptr<HttpAuthHandler> cur;
- int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
- cur_challenge, target, origin, net_log, &cur);
+ HttpAuthChallengeTokenizer challenge_tokenizer(cur_challenge.begin(),
+ cur_challenge.end());
+ std::string cur_auth_scheme = challenge_tokenizer.NormalizedScheme();
+ if (cur_auth_scheme.empty())
+ continue;
+
+ if (disabled_schemes.Contains(cur_auth_scheme))
+ continue;
+
+ // Always prefer the highest priority scheme available. If two handlers are
+ // of equal priority, then the handler based on the earlier challenge wins.
+ int cur_priority = GetSchemePriority(cur_auth_scheme);
+ if (best.get() && best_priority >= cur_priority)
+ continue;
+
+ // Immediately trying to create a handler may be wasteful because we may see
+ // a higher ranking challenge later on in the headers. However, this is
+ // rare. Servers typically specify higher priority schemes before lower
+ // priority schemes.
+ scoped_ptr<HttpAuthHandler> current_handler;
+ int rv = http_auth_handler_factory->CreateAuthHandler(
+ &challenge_tokenizer, target, origin,
+ HttpAuthHandlerFactory::CREATE_CHALLENGE, 1, net_log, &current_handler);
if (rv != OK) {
- VLOG(1) << "Unable to create AuthHandler. Status: "
- << ErrorToString(rv) << " Challenge: " << cur_challenge;
+ net_log.AddEvent(
+ NetLog::TYPE_AUTH_HANDLER_CREATION_FAILURE,
+ base::Bind(&AuthHandlerCreationFailureParams, &cur_challenge, rv));
continue;
}
- if (cur.get() && (!best.get() || best->score() < cur->score()) &&
- (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end()))
- best.swap(cur);
+ DCHECK(current_handler.get());
+ DCHECK_EQ(cur_auth_scheme, current_handler->auth_scheme());
+ best.swap(current_handler);
+ best_priority = cur_priority;
}
handler->swap(best);
}
@@ -59,16 +130,15 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
HttpAuthHandler* handler,
const HttpResponseHeaders* headers,
Target target,
- const std::set<Scheme>& disabled_schemes,
+ const HttpAuthSchemeSet& disabled_schemes,
std::string* challenge_used) {
DCHECK(handler);
DCHECK(headers);
DCHECK(challenge_used);
challenge_used->clear();
- HttpAuth::Scheme current_scheme = handler->auth_scheme();
- if (disabled_schemes.find(current_scheme) != disabled_schemes.end())
+ const std::string& current_scheme = handler->auth_scheme();
+ if (disabled_schemes.Contains(current_scheme))
return HttpAuth::AUTHORIZATION_RESULT_REJECT;
- std::string current_scheme_name = SchemeToString(current_scheme);
const std::string header_name = GetChallengeHeaderName(target);
void* iter = NULL;
std::string challenge;
@@ -76,8 +146,7 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
HttpAuth::AUTHORIZATION_RESULT_INVALID;
while (headers->EnumerateHeader(&iter, header_name, &challenge)) {
HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end());
- if (!base::LowerCaseEqualsASCII(props.scheme(),
- current_scheme_name.c_str()))
+ if (!props.SchemeIs(current_scheme))
continue;
authorization_result = handler->HandleAnotherChallenge(&props);
if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) {
@@ -129,22 +198,9 @@ std::string HttpAuth::GetAuthTargetString(Target target) {
}
// static
-const char* HttpAuth::SchemeToString(Scheme scheme) {
- static const char* const kSchemeNames[] = {
- "basic",
- "digest",
- "ntlm",
- "negotiate",
- "spdyproxy",
- "mock",
- };
- 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];
+bool HttpAuth::IsValidNormalizedScheme(const std::string& scheme) {
+ return HttpUtil::IsToken(scheme.begin(), scheme.end()) &&
+ base::ToLowerASCII(scheme) == scheme;
}
} // namespace net
« no previous file with comments | « net/http/http_auth.h ('k') | net/http/http_auth_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698