blob: e3e7fd71198d94d8f841eab637ff3c4d7f9b733e [file] [log] [blame]
Andreea Costinase45d54b2020-03-10 09:21:14 +01001// Copyright 2020 The Chromium OS 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
5#include "system-proxy/proxy_connect_job.h"
6
7#include <netinet/in.h>
8#include <sys/socket.h>
9#include <sys/types.h>
10
11#include <gmock/gmock.h>
12#include <gtest/gtest.h>
13#include <utility>
14
Andreea Costinase45d54b2020-03-10 09:21:14 +010015#include <base/bind.h>
16#include <base/bind_helpers.h>
17#include <base/callback_helpers.h>
18#include <base/files/file_util.h>
19#include <base/files/scoped_file.h>
Qijiang Fan34014672020-07-20 16:05:38 +090020#include <base/task/single_thread_task_executor.h>
Andreea Costinas08a5d182020-04-29 22:12:47 +020021#include <base/test/test_mock_time_task_runner.h>
Andreea Costinase45d54b2020-03-10 09:21:14 +010022#include <brillo/message_loops/base_message_loop.h>
Garrick Evanscd8c2972020-04-14 14:35:52 +090023#include <chromeos/patchpanel/socket.h>
24#include <chromeos/patchpanel/socket_forwarder.h>
Andreea Costinase45d54b2020-03-10 09:21:14 +010025
26#include "bindings/worker_common.pb.h"
27#include "system-proxy/protobuf_util.h"
Andreea Costinas054fbb52020-06-12 20:46:22 +020028#include "system-proxy/test_http_server.h"
Andreea Costinase45d54b2020-03-10 09:21:14 +010029
30namespace {
Andreea Costinas054fbb52020-06-12 20:46:22 +020031
32constexpr char kProxyServerUrl[] = "http://127.0.0.1:3128";
Andreea Costinasbb2aa022020-06-13 00:03:23 +020033constexpr char kCredentials[] = "username:pwd";
Andreea Costinas054fbb52020-06-12 20:46:22 +020034constexpr char kValidConnectRequest[] =
35 "CONNECT www.example.server.com:443 HTTP/1.1\r\n\r\n";
Andreea Costinase45d54b2020-03-10 09:21:14 +010036} // namespace
37
38namespace system_proxy {
39
40using ::testing::_;
41using ::testing::Return;
42
43class ProxyConnectJobTest : public ::testing::Test {
44 public:
Andreea Costinasbb2aa022020-06-13 00:03:23 +020045 struct HttpAuthEntry {
46 HttpAuthEntry(const std::string& origin,
47 const std::string& scheme,
48 const std::string& realm,
49 const std::string& credentials)
50 : origin(origin),
51 scheme(scheme),
52 realm(realm),
53 credentials(credentials) {}
54 std::string origin;
55 std::string scheme;
56 std::string realm;
57 std::string credentials;
58 };
Andreea Costinase45d54b2020-03-10 09:21:14 +010059 ProxyConnectJobTest() = default;
60 ProxyConnectJobTest(const ProxyConnectJobTest&) = delete;
61 ProxyConnectJobTest& operator=(const ProxyConnectJobTest&) = delete;
62 ~ProxyConnectJobTest() = default;
63
64 void SetUp() override {
65 int fds[2];
66 ASSERT_NE(-1,
67 socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
68 0 /* protocol */, fds));
69 cros_client_socket_ =
Garrick Evans3388a032020-03-24 11:25:55 +090070 std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[1]));
Andreea Costinase45d54b2020-03-10 09:21:14 +010071
72 connect_job_ = std::make_unique<ProxyConnectJob>(
Garrick Evans3388a032020-03-24 11:25:55 +090073 std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[0])), "",
Andreea Costinase45d54b2020-03-10 09:21:14 +010074 base::BindOnce(&ProxyConnectJobTest::ResolveProxy,
75 base::Unretained(this)),
Andreea Costinased9e6122020-08-12 12:06:19 +020076 base::BindRepeating(&ProxyConnectJobTest::OnAuthCredentialsRequired,
77 base::Unretained(this)),
Andreea Costinase45d54b2020-03-10 09:21:14 +010078 base::BindOnce(&ProxyConnectJobTest::OnConnectionSetupFinished,
79 base::Unretained(this)));
Andreea Costinase45d54b2020-03-10 09:21:14 +010080 }
Andreea Costinasbb2aa022020-06-13 00:03:23 +020081 void AddHttpAuthEntry(const std::string& origin,
82 const std::string& scheme,
83 const std::string& realm,
84 const std::string& credentials) {
85 http_auth_cache_.push_back(
86 HttpAuthEntry(origin, scheme, realm, credentials));
87 }
88
89 bool AuthRequested() { return auth_requested_; }
Andreea Costinase45d54b2020-03-10 09:21:14 +010090
91 protected:
92 void ResolveProxy(
93 const std::string& target_url,
94 base::OnceCallback<void(const std::list<std::string>&)> callback) {
Andreea Costinas054fbb52020-06-12 20:46:22 +020095 std::move(callback).Run({remote_proxy_url_});
Andreea Costinase45d54b2020-03-10 09:21:14 +010096 }
97
Andreea Costinased9e6122020-08-12 12:06:19 +020098 void OnAuthCredentialsRequired(
Andreea Costinasbb2aa022020-06-13 00:03:23 +020099 const std::string& proxy_url,
100 const std::string& scheme,
101 const std::string& realm,
Andreea Costinased9e6122020-08-12 12:06:19 +0200102 const std::string& bad_credentials,
103 base::RepeatingCallback<void(const std::string&)> callback) {
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200104 auth_requested_ = true;
105 for (const auto& auth_entry : http_auth_cache_) {
106 if (auth_entry.origin == proxy_url && auth_entry.realm == realm &&
107 auth_entry.scheme == scheme) {
108 std::move(callback).Run(auth_entry.credentials);
109 return;
110 }
111 }
Andreea Costinased9e6122020-08-12 12:06:19 +0200112 if (invoke_authentication_callback_) {
113 std::move(callback).Run(/* credentials = */ "");
114 }
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200115 }
116
Andreea Costinase45d54b2020-03-10 09:21:14 +0100117 void OnConnectionSetupFinished(
Garrick Evans3388a032020-03-24 11:25:55 +0900118 std::unique_ptr<patchpanel::SocketForwarder> fwd,
Andreea Costinase45d54b2020-03-10 09:21:14 +0100119 ProxyConnectJob* connect_job) {
120 ASSERT_EQ(connect_job, connect_job_.get());
Andreea Costinas054fbb52020-06-12 20:46:22 +0200121 if (fwd) {
122 forwarder_created_ = true;
123 }
Andreea Costinase45d54b2020-03-10 09:21:14 +0100124 }
125
Andreea Costinas054fbb52020-06-12 20:46:22 +0200126 std::string remote_proxy_url_ = kProxyServerUrl;
127 bool forwarder_created_ = false;
Andreea Costinased9e6122020-08-12 12:06:19 +0200128 // Used to simulate time-outs while waiting for credentials from the Browser.
129 bool invoke_authentication_callback_ = true;
Andreea Costinase45d54b2020-03-10 09:21:14 +0100130 std::unique_ptr<ProxyConnectJob> connect_job_;
Qijiang Fan34014672020-07-20 16:05:38 +0900131 base::SingleThreadTaskExecutor task_executor_{base::MessagePumpType::IO};
132 std::unique_ptr<brillo::BaseMessageLoop> brillo_loop_{
133 std::make_unique<brillo::BaseMessageLoop>(task_executor_.task_runner())};
Garrick Evans3388a032020-03-24 11:25:55 +0900134 std::unique_ptr<patchpanel::Socket> cros_client_socket_;
Andreea Costinas08a5d182020-04-29 22:12:47 +0200135
136 private:
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200137 std::vector<HttpAuthEntry> http_auth_cache_;
138 bool auth_requested_ = false;
Andreea Costinas08a5d182020-04-29 22:12:47 +0200139 FRIEND_TEST(ProxyConnectJobTest, ClientConnectTimeoutJobCanceled);
Andreea Costinase45d54b2020-03-10 09:21:14 +0100140};
141
142TEST_F(ProxyConnectJobTest, SuccessfulConnection) {
Andreea Costinas054fbb52020-06-12 20:46:22 +0200143 HttpTestServer http_test_server;
144 http_test_server.AddHttpConnectReply(HttpTestServer::HttpConnectReply::kOk);
145 http_test_server.Start();
146 remote_proxy_url_ = http_test_server.GetUrl();
147
Andreea Costinas08a5d182020-04-29 22:12:47 +0200148 connect_job_->Start();
Andreea Costinas054fbb52020-06-12 20:46:22 +0200149 cros_client_socket_->SendTo(kValidConnectRequest,
150 std::strlen(kValidConnectRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900151 brillo_loop_->RunOnce(false);
Andreea Costinase45d54b2020-03-10 09:21:14 +0100152
Andreea Costinasa2246592020-04-12 23:24:01 +0200153 EXPECT_EQ("www.example.server.com:443", connect_job_->target_url_);
Andreea Costinase45d54b2020-03-10 09:21:14 +0100154 EXPECT_EQ(1, connect_job_->proxy_servers_.size());
Andreea Costinas054fbb52020-06-12 20:46:22 +0200155 EXPECT_EQ(http_test_server.GetUrl(), connect_job_->proxy_servers_.front());
156 EXPECT_TRUE(forwarder_created_);
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200157 ASSERT_FALSE(AuthRequested());
Andreea Costinase45d54b2020-03-10 09:21:14 +0100158}
159
Andreea Costinasf90a4c02020-06-12 22:30:51 +0200160TEST_F(ProxyConnectJobTest, TunnelFailedBadGatewayFromRemote) {
161 HttpTestServer http_test_server;
162 http_test_server.AddHttpConnectReply(
163 HttpTestServer::HttpConnectReply::kBadGateway);
164 http_test_server.Start();
165 remote_proxy_url_ = http_test_server.GetUrl();
166
167 connect_job_->Start();
168 cros_client_socket_->SendTo(kValidConnectRequest,
169 std::strlen(kValidConnectRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900170 brillo_loop_->RunOnce(false);
Andreea Costinasf90a4c02020-06-12 22:30:51 +0200171
172 EXPECT_FALSE(forwarder_created_);
173
174 std::string expected_server_reply =
175 "HTTP/1.1 502 Error creating tunnel - Origin: local proxy\r\n\r\n";
176 std::vector<char> buf(expected_server_reply.size());
177 ASSERT_TRUE(cros_client_socket_->RecvFrom(buf.data(), buf.size()));
178 std::string actual_server_reply(buf.data(), buf.size());
179
180 EXPECT_EQ(expected_server_reply, actual_server_reply);
181}
182
Andreea Costinased3f9782020-05-20 17:09:46 +0200183TEST_F(ProxyConnectJobTest, SuccessfulConnectionAltEnding) {
Andreea Costinas054fbb52020-06-12 20:46:22 +0200184 HttpTestServer http_test_server;
185 http_test_server.AddHttpConnectReply(HttpTestServer::HttpConnectReply::kOk);
186 http_test_server.Start();
187 remote_proxy_url_ = http_test_server.GetUrl();
188
Andreea Costinased3f9782020-05-20 17:09:46 +0200189 connect_job_->Start();
Andreea Costinas054fbb52020-06-12 20:46:22 +0200190 char validConnRequest[] = "CONNECT www.example.server.com:443 HTTP/1.1\r\n\n";
Andreea Costinased3f9782020-05-20 17:09:46 +0200191 cros_client_socket_->SendTo(validConnRequest, std::strlen(validConnRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900192 brillo_loop_->RunOnce(false);
Andreea Costinased3f9782020-05-20 17:09:46 +0200193
194 EXPECT_EQ("www.example.server.com:443", connect_job_->target_url_);
195 EXPECT_EQ(1, connect_job_->proxy_servers_.size());
Andreea Costinas054fbb52020-06-12 20:46:22 +0200196 EXPECT_EQ(http_test_server.GetUrl(), connect_job_->proxy_servers_.front());
197 EXPECT_TRUE(forwarder_created_);
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200198 ASSERT_FALSE(AuthRequested());
Andreea Costinased3f9782020-05-20 17:09:46 +0200199}
200
Andreea Costinase45d54b2020-03-10 09:21:14 +0100201TEST_F(ProxyConnectJobTest, BadHttpRequestWrongMethod) {
Andreea Costinas08a5d182020-04-29 22:12:47 +0200202 connect_job_->Start();
Andreea Costinase45d54b2020-03-10 09:21:14 +0100203 char badConnRequest[] = "GET www.example.server.com:443 HTTP/1.1\r\n\r\n";
204 cros_client_socket_->SendTo(badConnRequest, std::strlen(badConnRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900205 brillo_loop_->RunOnce(false);
Andreea Costinase45d54b2020-03-10 09:21:14 +0100206
207 EXPECT_EQ("", connect_job_->target_url_);
208 EXPECT_EQ(0, connect_job_->proxy_servers_.size());
209 const std::string expected_http_response =
210 "HTTP/1.1 400 Bad Request - Origin: local proxy\r\n\r\n";
211 std::vector<char> buf(expected_http_response.size());
212 ASSERT_TRUE(
213 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
214 std::string actual_response(buf.data(), buf.size());
215 EXPECT_EQ(expected_http_response, actual_response);
216}
217
218TEST_F(ProxyConnectJobTest, BadHttpRequestNoEmptyLine) {
Andreea Costinas08a5d182020-04-29 22:12:47 +0200219 connect_job_->Start();
Andreea Costinase45d54b2020-03-10 09:21:14 +0100220 // No empty line after http message.
221 char badConnRequest[] = "CONNECT www.example.server.com:443 HTTP/1.1\r\n";
222 cros_client_socket_->SendTo(badConnRequest, std::strlen(badConnRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900223 brillo_loop_->RunOnce(false);
Andreea Costinase45d54b2020-03-10 09:21:14 +0100224
225 EXPECT_EQ("", connect_job_->target_url_);
226 EXPECT_EQ(0, connect_job_->proxy_servers_.size());
227 const std::string expected_http_response =
228 "HTTP/1.1 400 Bad Request - Origin: local proxy\r\n\r\n";
229 std::vector<char> buf(expected_http_response.size());
230 ASSERT_TRUE(
231 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
232 std::string actual_response(buf.data(), buf.size());
233 EXPECT_EQ(expected_http_response, actual_response);
234}
235
Andreea Costinas08a5d182020-04-29 22:12:47 +0200236TEST_F(ProxyConnectJobTest, WaitClientConnectTimeout) {
237 // Add a TaskRunner where we can control time.
238 scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
239 new base::TestMockTimeTaskRunner()};
Qijiang Fan34014672020-07-20 16:05:38 +0900240 brillo_loop_ = nullptr;
241 brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
Andreea Costinas08a5d182020-04-29 22:12:47 +0200242 base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());
243
244 connect_job_->Start();
245
246 EXPECT_EQ(1, task_runner->GetPendingTaskCount());
247 // Move the time ahead so that the client connection timeout callback is
248 // triggered.
249 task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
250
251 const std::string expected_http_response =
252 "HTTP/1.1 408 Request Timeout - Origin: local proxy\r\n\r\n";
253 std::vector<char> buf(expected_http_response.size());
254 ASSERT_TRUE(
255 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
256 std::string actual_response(buf.data(), buf.size());
257
258 EXPECT_EQ(expected_http_response, actual_response);
259}
260
261// Check that the client connect timeout callback is not fired if the owning
262// proxy connect job is destroyed.
263TEST_F(ProxyConnectJobTest, ClientConnectTimeoutJobCanceled) {
264 // Add a TaskRunner where we can control time.
265 scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
266 new base::TestMockTimeTaskRunner()};
Qijiang Fan34014672020-07-20 16:05:38 +0900267 brillo_loop_ = nullptr;
268 brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
Andreea Costinas08a5d182020-04-29 22:12:47 +0200269 base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());
270
271 // Create a proxy connect job and start the client connect timeout counter.
272 {
273 int fds[2];
274 ASSERT_NE(-1,
275 socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
276 0 /* protocol */, fds));
277 auto client_socket =
278 std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[1]));
279
280 auto connect_job = std::make_unique<ProxyConnectJob>(
281 std::make_unique<patchpanel::Socket>(base::ScopedFD(fds[0])), "",
282 base::BindOnce(&ProxyConnectJobTest::ResolveProxy,
283 base::Unretained(this)),
Andreea Costinased9e6122020-08-12 12:06:19 +0200284 base::BindRepeating(&ProxyConnectJobTest::OnAuthCredentialsRequired,
285 base::Unretained(this)),
Andreea Costinas08a5d182020-04-29 22:12:47 +0200286 base::BindOnce(&ProxyConnectJobTest::OnConnectionSetupFinished,
287 base::Unretained(this)));
288 // Post the timeout task.
289 connect_job->Start();
290 EXPECT_TRUE(task_runner->HasPendingTask());
291 }
292 // Check that the task was canceled.
293 EXPECT_FALSE(task_runner->HasPendingTask());
294}
295
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200296// Test that the the CONNECT request is sent again after acquiring credentials.
297TEST_F(ProxyConnectJobTest, ResendWithCredentials) {
298 // Start the test server
299 HttpTestServer http_test_server;
300 http_test_server.AddHttpConnectReply(
301 HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
302 http_test_server.AddHttpConnectReply(HttpTestServer::HttpConnectReply::kOk);
303 http_test_server.Start();
304 remote_proxy_url_ = http_test_server.GetUrl();
305
306 AddHttpAuthEntry(remote_proxy_url_, "Basic", "\"My Proxy\"", kCredentials);
307 connect_job_->Start();
308
309 cros_client_socket_->SendTo(kValidConnectRequest,
310 std::strlen(kValidConnectRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900311 brillo_loop_->RunOnce(false);
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200312
313 ASSERT_TRUE(AuthRequested());
314 EXPECT_TRUE(forwarder_created_);
315 EXPECT_EQ(kCredentials, connect_job_->credentials_);
316 EXPECT_EQ(200, connect_job_->http_response_code_);
317}
318
319// Test that the proxy auth required status is forwarded to the client if
320// credentials are missing.
321TEST_F(ProxyConnectJobTest, NoCredentials) {
322 // Start the test server
323 HttpTestServer http_test_server;
324 http_test_server.AddHttpConnectReply(
325 HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
326 http_test_server.Start();
327 remote_proxy_url_ = http_test_server.GetUrl();
328
329 connect_job_->Start();
330
331 cros_client_socket_->SendTo(kValidConnectRequest,
332 std::strlen(kValidConnectRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900333 brillo_loop_->RunOnce(false);
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200334
335 ASSERT_TRUE(AuthRequested());
336 EXPECT_EQ("", connect_job_->credentials_);
337 EXPECT_EQ(407, connect_job_->http_response_code_);
338}
339
340// Test that the proxy auth required status is forwarded to the client if the
341// server chose Kerberos as an authentication method.
342TEST_F(ProxyConnectJobTest, KerberosAuth) {
343 // Start the test server
344 HttpTestServer http_test_server;
345 http_test_server.AddHttpConnectReply(
346 HttpTestServer::HttpConnectReply::kAuthRequiredKerberos);
347 http_test_server.Start();
348 remote_proxy_url_ = http_test_server.GetUrl();
349
350 connect_job_->Start();
351
352 cros_client_socket_->SendTo(kValidConnectRequest,
353 std::strlen(kValidConnectRequest));
Qijiang Fan34014672020-07-20 16:05:38 +0900354 brillo_loop_->RunOnce(false);
Andreea Costinasbb2aa022020-06-13 00:03:23 +0200355
356 ASSERT_FALSE(AuthRequested());
357 EXPECT_EQ("", connect_job_->credentials_);
358 EXPECT_EQ(407, connect_job_->http_response_code_);
359}
360
Andreea Costinased9e6122020-08-12 12:06:19 +0200361// Test that the connection times out while waiting for credentials from the
362// Browser.
363TEST_F(ProxyConnectJobTest, AuthenticationTimeout) {
364 // Add a TaskRunner where we can control time.
365 scoped_refptr<base::TestMockTimeTaskRunner> task_runner{
366 new base::TestMockTimeTaskRunner()};
367 brillo_loop_ = nullptr;
368 brillo_loop_ = std::make_unique<brillo::BaseMessageLoop>(task_runner);
369 base::TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner.get());
370
371 invoke_authentication_callback_ = false;
372
373 // Start the test server
374 HttpTestServer http_test_server;
375 http_test_server.AddHttpConnectReply(
376 HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
377 http_test_server.Start();
378 remote_proxy_url_ = http_test_server.GetUrl();
379
380 connect_job_->Start();
381
382 cros_client_socket_->SendTo(kValidConnectRequest,
383 std::strlen(kValidConnectRequest));
384 task_runner->RunUntilIdle();
385 // We need to manually invoke the method which reads from the client socket
386 // because |task_runner| will not execute the FileDescriptorWatcher's tasks.
387 connect_job_->OnClientReadReady();
388
389 // Check that an authentication request was sent.
390 ASSERT_TRUE(AuthRequested());
391 EXPECT_EQ(1, task_runner->GetPendingTaskCount());
392 // Move the time ahead so that the client connection timeout callback is
393 // triggered.
394 task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
395
396 const std::string expected_http_response =
397 "HTTP/1.1 407 Credentials required - Origin: local proxy\r\n\r\n";
398 std::vector<char> buf(expected_http_response.size());
399 ASSERT_TRUE(
400 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
401 std::string actual_response(buf.data(), buf.size());
402
403 // Check that the auth failure was forwarded to the client.
404 EXPECT_EQ(expected_http_response, actual_response);
405}
406
407// Verifies that the receiving the same bad credentials twice will send an auth
408// failure to the Chrome OS local client.
409TEST_F(ProxyConnectJobTest, CancelIfBadCredentials) {
410 // Start the test server
411 HttpTestServer http_test_server;
412 http_test_server.AddHttpConnectReply(
413 HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
414 http_test_server.AddHttpConnectReply(
415 HttpTestServer::HttpConnectReply::kAuthRequiredBasic);
416 http_test_server.Start();
417 remote_proxy_url_ = http_test_server.GetUrl();
418 AddHttpAuthEntry(remote_proxy_url_, "Basic", "\"My Proxy\"", kCredentials);
419
420 connect_job_->Start();
421
422 cros_client_socket_->SendTo(kValidConnectRequest,
423 std::strlen(kValidConnectRequest));
424 brillo_loop_->RunOnce(false);
425
426 ASSERT_TRUE(AuthRequested());
427
428 const std::string expected_http_response =
429 "HTTP/1.1 407 Credentials required - Origin: local proxy\r\n\r\n";
430 std::vector<char> buf(expected_http_response.size());
431 ASSERT_TRUE(
432 base::ReadFromFD(cros_client_socket_->fd(), buf.data(), buf.size()));
433 std::string actual_response(buf.data(), buf.size());
434
435 EXPECT_EQ(expected_http_response, actual_response);
436}
437
Andreea Costinase45d54b2020-03-10 09:21:14 +0100438} // namespace system_proxy