http_auth.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/http/http_auth.h"
  5. #include <algorithm>
  6. #include "base/strings/string_tokenizer.h"
  7. #include "base/strings/string_util.h"
  8. #include "base/values.h"
  9. #include "net/base/net_errors.h"
  10. #include "net/dns/host_resolver.h"
  11. #include "net/http/http_auth_challenge_tokenizer.h"
  12. #include "net/http/http_auth_handler.h"
  13. #include "net/http/http_auth_handler_factory.h"
  14. #include "net/http/http_auth_scheme.h"
  15. #include "net/http/http_request_headers.h"
  16. #include "net/http/http_response_headers.h"
  17. #include "net/http/http_util.h"
  18. #include "net/log/net_log.h"
  19. #include "net/log/net_log_values.h"
  20. namespace net {
  21. namespace {
  22. const char* const kSchemeNames[] = {kBasicAuthScheme, kDigestAuthScheme,
  23. kNtlmAuthScheme, kNegotiateAuthScheme,
  24. kSpdyProxyAuthScheme, kMockAuthScheme};
  25. } // namespace
  26. HttpAuth::Identity::Identity() = default;
  27. // static
  28. void HttpAuth::ChooseBestChallenge(
  29. HttpAuthHandlerFactory* http_auth_handler_factory,
  30. const HttpResponseHeaders& response_headers,
  31. const SSLInfo& ssl_info,
  32. const NetworkIsolationKey& network_isolation_key,
  33. Target target,
  34. const url::SchemeHostPort& scheme_host_port,
  35. const std::set<Scheme>& disabled_schemes,
  36. const NetLogWithSource& net_log,
  37. HostResolver* host_resolver,
  38. std::unique_ptr<HttpAuthHandler>* handler) {
  39. DCHECK(http_auth_handler_factory);
  40. DCHECK(handler->get() == nullptr);
  41. // Choose the challenge whose authentication handler gives the maximum score.
  42. std::unique_ptr<HttpAuthHandler> best;
  43. const std::string header_name = GetChallengeHeaderName(target);
  44. std::string cur_challenge;
  45. size_t iter = 0;
  46. while (response_headers.EnumerateHeader(&iter, header_name, &cur_challenge)) {
  47. std::unique_ptr<HttpAuthHandler> cur;
  48. int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
  49. cur_challenge, target, ssl_info, network_isolation_key,
  50. scheme_host_port, net_log, host_resolver, &cur);
  51. if (rv != OK) {
  52. VLOG(1) << "Unable to create AuthHandler. Status: "
  53. << ErrorToString(rv) << " Challenge: " << cur_challenge;
  54. continue;
  55. }
  56. if (cur.get() && (!best.get() || best->score() < cur->score()) &&
  57. (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end()))
  58. best.swap(cur);
  59. }
  60. handler->swap(best);
  61. }
  62. // static
  63. HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse(
  64. HttpAuthHandler* handler,
  65. const HttpResponseHeaders& response_headers,
  66. Target target,
  67. const std::set<Scheme>& disabled_schemes,
  68. std::string* challenge_used) {
  69. DCHECK(handler);
  70. DCHECK(challenge_used);
  71. challenge_used->clear();
  72. HttpAuth::Scheme current_scheme = handler->auth_scheme();
  73. if (disabled_schemes.find(current_scheme) != disabled_schemes.end())
  74. return HttpAuth::AUTHORIZATION_RESULT_REJECT;
  75. const char* current_scheme_name = SchemeToString(current_scheme);
  76. const std::string header_name = GetChallengeHeaderName(target);
  77. size_t iter = 0;
  78. std::string challenge;
  79. HttpAuth::AuthorizationResult authorization_result =
  80. HttpAuth::AUTHORIZATION_RESULT_INVALID;
  81. while (response_headers.EnumerateHeader(&iter, header_name, &challenge)) {
  82. HttpAuthChallengeTokenizer challenge_tokens(challenge.begin(),
  83. challenge.end());
  84. if (challenge_tokens.auth_scheme() != current_scheme_name)
  85. continue;
  86. authorization_result = handler->HandleAnotherChallenge(&challenge_tokens);
  87. if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) {
  88. *challenge_used = challenge;
  89. return authorization_result;
  90. }
  91. }
  92. // Finding no matches is equivalent to rejection.
  93. return HttpAuth::AUTHORIZATION_RESULT_REJECT;
  94. }
  95. // static
  96. std::string HttpAuth::GetChallengeHeaderName(Target target) {
  97. switch (target) {
  98. case AUTH_PROXY:
  99. return "Proxy-Authenticate";
  100. case AUTH_SERVER:
  101. return "WWW-Authenticate";
  102. default:
  103. NOTREACHED();
  104. return std::string();
  105. }
  106. }
  107. // static
  108. std::string HttpAuth::GetAuthorizationHeaderName(Target target) {
  109. switch (target) {
  110. case AUTH_PROXY:
  111. return HttpRequestHeaders::kProxyAuthorization;
  112. case AUTH_SERVER:
  113. return HttpRequestHeaders::kAuthorization;
  114. default:
  115. NOTREACHED();
  116. return std::string();
  117. }
  118. }
  119. // static
  120. std::string HttpAuth::GetAuthTargetString(Target target) {
  121. switch (target) {
  122. case AUTH_PROXY:
  123. return "proxy";
  124. case AUTH_SERVER:
  125. return "server";
  126. default:
  127. NOTREACHED();
  128. return std::string();
  129. }
  130. }
  131. // static
  132. const char* HttpAuth::SchemeToString(Scheme scheme) {
  133. static_assert(std::size(kSchemeNames) == AUTH_SCHEME_MAX,
  134. "http auth scheme names incorrect size");
  135. if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) {
  136. NOTREACHED();
  137. return "invalid_scheme";
  138. }
  139. return kSchemeNames[scheme];
  140. }
  141. // static
  142. HttpAuth::Scheme HttpAuth::StringToScheme(const std::string& str) {
  143. for (uint8_t i = 0; i < std::size(kSchemeNames); i++) {
  144. if (str == kSchemeNames[i])
  145. return static_cast<Scheme>(i);
  146. }
  147. NOTREACHED();
  148. return AUTH_SCHEME_MAX;
  149. }
  150. // static
  151. const char* HttpAuth::AuthorizationResultToString(
  152. AuthorizationResult authorization_result) {
  153. switch (authorization_result) {
  154. case AUTHORIZATION_RESULT_ACCEPT:
  155. return "accept";
  156. case AUTHORIZATION_RESULT_REJECT:
  157. return "reject";
  158. case AUTHORIZATION_RESULT_STALE:
  159. return "stale";
  160. case AUTHORIZATION_RESULT_INVALID:
  161. return "invalid";
  162. case AUTHORIZATION_RESULT_DIFFERENT_REALM:
  163. return "different_realm";
  164. }
  165. NOTREACHED();
  166. return "(invalid result)";
  167. }
  168. // static
  169. base::Value HttpAuth::NetLogAuthorizationResultParams(
  170. const char* name,
  171. AuthorizationResult authorization_result) {
  172. return NetLogParamsWithString(
  173. name, AuthorizationResultToString(authorization_result));
  174. }
  175. } // namespace net