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_handler_mock.h"
11
12 #include <utility>
13
14 #include "base/functional/bind.h"
15 #include "base/location.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/strings/string_util.h"
18 #include "base/task/single_thread_task_runner.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_request_info.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace net {
27
PrintTo(const HttpAuthHandlerMock::State & state,::std::ostream * os)28 void PrintTo(const HttpAuthHandlerMock::State& state, ::std::ostream* os) {
29 switch (state) {
30 case HttpAuthHandlerMock::State::WAIT_FOR_INIT:
31 *os << "WAIT_FOR_INIT";
32 break;
33 case HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE:
34 *os << "WAIT_FOR_CHALLENGE";
35 break;
36 case HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN:
37 *os << "WAIT_FOR_GENERATE_AUTH_TOKEN";
38 break;
39 case HttpAuthHandlerMock::State::TOKEN_PENDING:
40 *os << "TOKEN_PENDING";
41 break;
42 case HttpAuthHandlerMock::State::DONE:
43 *os << "DONE";
44 break;
45 }
46 }
47
48 HttpAuthHandlerMock::HttpAuthHandlerMock() = default;
49
50 HttpAuthHandlerMock::~HttpAuthHandlerMock() = default;
51
SetGenerateExpectation(bool async,int rv)52 void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
53 generate_async_ = async;
54 generate_rv_ = rv;
55 }
56
NeedsIdentity()57 bool HttpAuthHandlerMock::NeedsIdentity() {
58 return first_round_;
59 }
60
AllowsDefaultCredentials()61 bool HttpAuthHandlerMock::AllowsDefaultCredentials() {
62 return allows_default_credentials_;
63 }
64
AllowsExplicitCredentials()65 bool HttpAuthHandlerMock::AllowsExplicitCredentials() {
66 return allows_explicit_credentials_;
67 }
68
Init(HttpAuthChallengeTokenizer * challenge,const SSLInfo & ssl_info,const NetworkAnonymizationKey & network_anonymization_key)69 bool HttpAuthHandlerMock::Init(
70 HttpAuthChallengeTokenizer* challenge,
71 const SSLInfo& ssl_info,
72 const NetworkAnonymizationKey& network_anonymization_key) {
73 EXPECT_EQ(State::WAIT_FOR_INIT, state_);
74 state_ = State::WAIT_FOR_GENERATE_AUTH_TOKEN;
75 auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
76 score_ = 1;
77 properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
78 return true;
79 }
80
GenerateAuthTokenImpl(const AuthCredentials * credentials,const HttpRequestInfo * request,CompletionOnceCallback callback,std::string * auth_token)81 int HttpAuthHandlerMock::GenerateAuthTokenImpl(
82 const AuthCredentials* credentials,
83 const HttpRequestInfo* request,
84 CompletionOnceCallback callback,
85 std::string* auth_token) {
86 EXPECT_EQ(State::WAIT_FOR_GENERATE_AUTH_TOKEN, state_);
87 first_round_ = false;
88 request_url_ = request->url;
89 if (generate_async_) {
90 EXPECT_TRUE(callback_.is_null());
91 EXPECT_TRUE(auth_token_ == nullptr);
92 callback_ = std::move(callback);
93 auth_token_ = auth_token;
94 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
95 FROM_HERE, base::BindOnce(&HttpAuthHandlerMock::OnGenerateAuthToken,
96 weak_factory_.GetWeakPtr()));
97 state_ = State::TOKEN_PENDING;
98 return ERR_IO_PENDING;
99 } else {
100 if (generate_rv_ == OK) {
101 *auth_token = "auth_token";
102 state_ = is_connection_based() ? State::WAIT_FOR_CHALLENGE
103 : State::WAIT_FOR_GENERATE_AUTH_TOKEN;
104 } else {
105 state_ = State::DONE;
106 }
107 return generate_rv_;
108 }
109 }
110
HandleAnotherChallengeImpl(HttpAuthChallengeTokenizer * challenge)111 HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallengeImpl(
112 HttpAuthChallengeTokenizer* challenge) {
113 EXPECT_THAT(state_, ::testing::AnyOf(State::WAIT_FOR_CHALLENGE,
114 State::WAIT_FOR_GENERATE_AUTH_TOKEN));
115 // If we receive an empty challenge for a connection based scheme, or a second
116 // challenge for a non connection based scheme, assume it's a rejection.
117 if (!is_connection_based() || challenge->base64_param().empty()) {
118 state_ = State::DONE;
119 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
120 }
121
122 if (challenge->auth_scheme() != "mock") {
123 state_ = State::DONE;
124 return HttpAuth::AUTHORIZATION_RESULT_INVALID;
125 }
126
127 state_ = State::WAIT_FOR_GENERATE_AUTH_TOKEN;
128 return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
129 }
130
OnGenerateAuthToken()131 void HttpAuthHandlerMock::OnGenerateAuthToken() {
132 EXPECT_TRUE(generate_async_);
133 EXPECT_TRUE(!callback_.is_null());
134 EXPECT_EQ(State::TOKEN_PENDING, state_);
135 if (generate_rv_ == OK) {
136 *auth_token_ = "auth_token";
137 state_ = is_connection_based() ? State::WAIT_FOR_CHALLENGE
138 : State::WAIT_FOR_GENERATE_AUTH_TOKEN;
139 } else {
140 state_ = State::DONE;
141 }
142 auth_token_ = nullptr;
143 std::move(callback_).Run(generate_rv_);
144 }
145
Factory()146 HttpAuthHandlerMock::Factory::Factory() {
147 // TODO(cbentzel): Default do_init_from_challenge_ to true.
148 }
149
150 HttpAuthHandlerMock::Factory::~Factory() = default;
151
AddMockHandler(std::unique_ptr<HttpAuthHandler> handler,HttpAuth::Target target)152 void HttpAuthHandlerMock::Factory::AddMockHandler(
153 std::unique_ptr<HttpAuthHandler> handler,
154 HttpAuth::Target target) {
155 handlers_[target].push_back(std::move(handler));
156 }
157
CreateAuthHandler(HttpAuthChallengeTokenizer * challenge,HttpAuth::Target target,const SSLInfo & ssl_info,const NetworkAnonymizationKey & network_anonymization_key,const url::SchemeHostPort & scheme_host_port,CreateReason reason,int nonce_count,const NetLogWithSource & net_log,HostResolver * host_resolver,std::unique_ptr<HttpAuthHandler> * handler)158 int HttpAuthHandlerMock::Factory::CreateAuthHandler(
159 HttpAuthChallengeTokenizer* challenge,
160 HttpAuth::Target target,
161 const SSLInfo& ssl_info,
162 const NetworkAnonymizationKey& network_anonymization_key,
163 const url::SchemeHostPort& scheme_host_port,
164 CreateReason reason,
165 int nonce_count,
166 const NetLogWithSource& net_log,
167 HostResolver* host_resolver,
168 std::unique_ptr<HttpAuthHandler>* handler) {
169 if (handlers_[target].empty())
170 return ERR_UNEXPECTED;
171 std::unique_ptr<HttpAuthHandler> tmp_handler =
172 std::move(handlers_[target][0]);
173 std::vector<std::unique_ptr<HttpAuthHandler>>& handlers = handlers_[target];
174 handlers.erase(handlers.begin());
175 if (do_init_from_challenge_ &&
176 !tmp_handler->InitFromChallenge(challenge, target, ssl_info,
177 network_anonymization_key,
178 scheme_host_port, net_log)) {
179 return ERR_INVALID_RESPONSE;
180 }
181 handler->swap(tmp_handler);
182 return OK;
183 }
184
185 } // namespace net
186