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