1 // Copyright 2013 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 #include <memory>
6 #include <ostream>
7 #include <utility>
8 #include <vector>
9
10 #include "base/compiler_specific.h"
11 #include "base/containers/span.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "net/base/completion_once_callback.h"
17 #include "net/base/elements_upload_data_stream.h"
18 #include "net/base/ip_address.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/base/upload_bytes_element_reader.h"
21 #include "net/base/upload_data_stream.h"
22 #include "net/cert/mock_cert_verifier.h"
23 #include "net/cert/multi_log_ct_verifier.h"
24 #include "net/dns/mapped_host_resolver.h"
25 #include "net/dns/mock_host_resolver.h"
26 #include "net/http/http_auth_handler_factory.h"
27 #include "net/http/http_network_session.h"
28 #include "net/http/http_network_transaction.h"
29 #include "net/http/http_server_properties.h"
30 #include "net/http/http_transaction_test_util.h"
31 #include "net/http/transport_security_state.h"
32 #include "net/log/net_log_with_source.h"
33 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
34 #include "net/quic/crypto_test_utils_chromium.h"
35 #include "net/quic/quic_context.h"
36 #include "net/socket/client_socket_factory.h"
37 #include "net/ssl/ssl_config_service_defaults.h"
38 #include "net/test/cert_test_util.h"
39 #include "net/test/gtest_util.h"
40 #include "net/test/test_data_directory.h"
41 #include "net/test/test_with_task_environment.h"
42 #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
43 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
44 #include "net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h"
45 #include "net/tools/quic/quic_simple_server.h"
46 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
47 #include "net/url_request/static_http_user_agent_settings.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 #include "testing/platform_test.h"
51
52 namespace net {
53
54 using test::IsOk;
55
56 namespace test {
57
58 namespace {
59
60 const char kResponseBody[] = "some arbitrary response body";
61
62 // Factory for creating HttpTransactions, used by TestTransactionConsumer.
63 class TestTransactionFactory : public HttpTransactionFactory {
64 public:
TestTransactionFactory(const HttpNetworkSessionParams & session_params,const HttpNetworkSessionContext & session_context)65 explicit TestTransactionFactory(
66 const HttpNetworkSessionParams& session_params,
67 const HttpNetworkSessionContext& session_context)
68 : session_(std::make_unique<HttpNetworkSession>(session_params,
69 session_context)) {}
70
71 ~TestTransactionFactory() override = default;
72
73 // HttpTransactionFactory methods
CreateTransaction(RequestPriority priority,std::unique_ptr<HttpTransaction> * trans)74 int CreateTransaction(RequestPriority priority,
75 std::unique_ptr<HttpTransaction>* trans) override {
76 *trans = std::make_unique<HttpNetworkTransaction>(priority, session_.get());
77 return OK;
78 }
79
GetCache()80 HttpCache* GetCache() override { return nullptr; }
81
GetSession()82 HttpNetworkSession* GetSession() override { return session_.get(); }
83
84 private:
85 std::unique_ptr<HttpNetworkSession> session_;
86 };
87
88 } // namespace
89
90 class QuicEndToEndTest : public ::testing::Test, public WithTaskEnvironment {
91 protected:
QuicEndToEndTest()92 QuicEndToEndTest()
93 : host_resolver_(CreateResolverImpl()),
94 ssl_config_service_(std::make_unique<SSLConfigServiceDefaults>()),
95 proxy_resolution_service_(
96 ConfiguredProxyResolutionService::CreateDirect()),
97 auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()) {
98 request_.method = "GET";
99 request_.url = GURL("https://test.example.com/");
100 request_.load_flags = 0;
101 request_.traffic_annotation =
102 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
103
104 session_params_.enable_quic = true;
105
106 session_context_.client_socket_factory =
107 ClientSocketFactory::GetDefaultFactory();
108 session_context_.quic_context = &quic_context_;
109 session_context_.host_resolver = &host_resolver_;
110 session_context_.cert_verifier = &cert_verifier_;
111 session_context_.transport_security_state = &transport_security_state_;
112 session_context_.proxy_resolution_service = proxy_resolution_service_.get();
113 session_context_.ssl_config_service = ssl_config_service_.get();
114 session_context_.http_user_agent_settings = &http_user_agent_settings_;
115 session_context_.http_auth_handler_factory = auth_handler_factory_.get();
116 session_context_.http_server_properties = &http_server_properties_;
117
118 CertVerifyResult verify_result;
119 verify_result.verified_cert =
120 ImportCertFromFile(GetTestCertsDirectory(), "quic-chain.pem");
121 cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(),
122 "test.example.com", verify_result,
123 OK);
124 }
125
126 // Creates a mock host resolver in which test.example.com
127 // resolves to localhost.
CreateResolverImpl()128 static std::unique_ptr<MockHostResolver> CreateResolverImpl() {
129 auto resolver = std::make_unique<MockHostResolver>();
130 resolver->rules()->AddRule("test.example.com", "127.0.0.1");
131 return resolver;
132 }
133
SetUp()134 void SetUp() override {
135 StartServer();
136
137 // Use a mapped host resolver so that request for test.example.com (port 80)
138 // reach the server running on localhost.
139 std::string map_rule =
140 "MAP test.example.com test.example.com:" +
141 base::NumberToString(server_->server_address().port());
142 EXPECT_TRUE(host_resolver_.AddRuleFromString(map_rule));
143
144 // To simplify the test, and avoid the race with the HTTP request, we force
145 // QUIC for these requests.
146 quic_context_.params()->origins_to_force_quic_on.insert(
147 HostPortPair::FromString("test.example.com:443"));
148
149 transaction_factory_ = std::make_unique<TestTransactionFactory>(
150 session_params_, session_context_);
151 }
152
TearDown()153 void TearDown() override {}
154
155 // Starts the QUIC server listening on a random port.
StartServer()156 void StartServer() {
157 server_address_ = IPEndPoint(IPAddress(127, 0, 0, 1), 0);
158 server_config_.SetInitialStreamFlowControlWindowToSend(
159 quic::test::kInitialStreamFlowControlWindowForTest);
160 server_config_.SetInitialSessionFlowControlWindowToSend(
161 quic::test::kInitialSessionFlowControlWindowForTest);
162 server_ = std::make_unique<QuicSimpleServer>(
163 net::test::ProofSourceForTestingChromium(), server_config_,
164 server_config_options_, AllSupportedQuicVersions(),
165 &memory_cache_backend_);
166 server_->Listen(server_address_);
167 server_address_ = server_->server_address();
168 server_->StartReading();
169 server_started_ = true;
170 }
171
172 // Adds an entry to the cache used by the QUIC server to serve
173 // responses.
AddToCache(std::string_view path,int response_code,std::string_view response_detail,std::string_view body)174 void AddToCache(std::string_view path,
175 int response_code,
176 std::string_view response_detail,
177 std::string_view body) {
178 memory_cache_backend_.AddSimpleResponse("test.example.com", path,
179 response_code, body);
180 }
181
182 // Populates |request_body_| with |length_| ASCII bytes.
GenerateBody(size_t length)183 void GenerateBody(size_t length) {
184 request_body_.clear();
185 request_body_.reserve(length);
186 for (size_t i = 0; i < length; ++i) {
187 request_body_.append(1, static_cast<char>(32 + i % (126 - 32)));
188 }
189 }
190
191 // Initializes |request_| for a post of |length| bytes.
InitializePostRequest(size_t length)192 void InitializePostRequest(size_t length) {
193 GenerateBody(length);
194 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
195 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
196 base::as_byte_span(request_body_)));
197 upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
198 std::move(element_readers), 0);
199 request_.method = "POST";
200 request_.url = GURL("https://test.example.com/");
201 request_.upload_data_stream = upload_data_stream_.get();
202 ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
203 NetLogWithSource()),
204 IsOk());
205 }
206
207 // Checks that |consumer| completed and received |status_line| and |body|.
CheckResponse(const TestTransactionConsumer & consumer,const std::string & status_line,const std::string & body)208 void CheckResponse(const TestTransactionConsumer& consumer,
209 const std::string& status_line,
210 const std::string& body) {
211 ASSERT_TRUE(consumer.is_done());
212 ASSERT_THAT(consumer.error(), IsOk());
213 EXPECT_EQ(status_line, consumer.response_info()->headers->GetStatusLine());
214 EXPECT_EQ(body, consumer.content());
215 }
216
217 QuicContext quic_context_;
218 MappedHostResolver host_resolver_;
219 MockCertVerifier cert_verifier_;
220 TransportSecurityState transport_security_state_;
221 std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
222 std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
223 std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
224 StaticHttpUserAgentSettings http_user_agent_settings_ = {"*", "test-ua"};
225 HttpServerProperties http_server_properties_;
226 HttpNetworkSessionParams session_params_;
227 HttpNetworkSessionContext session_context_;
228 std::unique_ptr<TestTransactionFactory> transaction_factory_;
229 std::string request_body_;
230 std::unique_ptr<UploadDataStream> upload_data_stream_;
231 HttpRequestInfo request_;
232 quic::QuicMemoryCacheBackend memory_cache_backend_;
233 std::unique_ptr<QuicSimpleServer> server_;
234 IPEndPoint server_address_;
235 std::string server_hostname_;
236 quic::QuicConfig server_config_;
237 quic::QuicCryptoServerConfig::ConfigOptions server_config_options_;
238 bool server_started_;
239 bool strike_register_no_startup_period_ = false;
240 };
241
TEST_F(QuicEndToEndTest,LargeGetWithNoPacketLoss)242 TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
243 std::string response(10 * 1024, 'x');
244
245 AddToCache(request_.url.PathForRequest(), 200, "OK", response);
246
247 TestTransactionConsumer consumer(DEFAULT_PRIORITY,
248 transaction_factory_.get());
249 consumer.Start(&request_, NetLogWithSource());
250
251 CheckResponse(consumer, "HTTP/1.1 200", response);
252 }
253
254 // crbug.com/559173
255 #if defined(THREAD_SANITIZER)
TEST_F(QuicEndToEndTest,DISABLED_LargePostWithNoPacketLoss)256 TEST_F(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) {
257 #else
258 TEST_F(QuicEndToEndTest, LargePostWithNoPacketLoss) {
259 #endif
260 InitializePostRequest(1024 * 1024);
261
262 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
263
264 TestTransactionConsumer consumer(DEFAULT_PRIORITY,
265 transaction_factory_.get());
266 consumer.Start(&request_, NetLogWithSource());
267
268 CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
269 }
270
271 // crbug.com/559173
272 #if defined(THREAD_SANITIZER)
273 TEST_F(QuicEndToEndTest, DISABLED_LargePostWithPacketLoss) {
274 #else
275 TEST_F(QuicEndToEndTest, LargePostWithPacketLoss) {
276 #endif
277 // FLAGS_fake_packet_loss_percentage = 30;
278 InitializePostRequest(1024 * 1024);
279
280 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
281
282 TestTransactionConsumer consumer(DEFAULT_PRIORITY,
283 transaction_factory_.get());
284 consumer.Start(&request_, NetLogWithSource());
285
286 CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
287 }
288
289 // crbug.com/536845
290 #if defined(THREAD_SANITIZER)
291 TEST_F(QuicEndToEndTest, DISABLED_UberTest) {
292 #else
293 TEST_F(QuicEndToEndTest, UberTest) {
294 #endif
295 // FLAGS_fake_packet_loss_percentage = 30;
296
297 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
298
299 std::vector<std::unique_ptr<TestTransactionConsumer>> consumers;
300 for (size_t i = 0; i < 100; ++i) {
301 TestTransactionConsumer* consumer = new TestTransactionConsumer(
302 DEFAULT_PRIORITY, transaction_factory_.get());
303 consumers.push_back(base::WrapUnique(consumer));
304 consumer->Start(&request_, NetLogWithSource());
305 }
306
307 for (const auto& consumer : consumers)
308 CheckResponse(*consumer.get(), "HTTP/1.1 200", kResponseBody);
309 }
310
311 TEST_F(QuicEndToEndTest, EnableMLKEM) {
312 // Enable ML-KEM on the client.
313 base::test::ScopedFeatureList scoped_feature_list;
314 scoped_feature_list.InitWithFeatures({features::kPostQuantumKyber}, {});
315
316 // Configure the server to only support ML-KEM.
317 server_->crypto_config()->set_preferred_groups({SSL_GROUP_X25519_MLKEM768});
318
319 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
320
321 TestTransactionConsumer consumer(DEFAULT_PRIORITY,
322 transaction_factory_.get());
323 consumer.Start(&request_, NetLogWithSource());
324
325 CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
326 EXPECT_EQ(consumer.response_info()->ssl_info.key_exchange_group,
327 SSL_GROUP_X25519_MLKEM768);
328 }
329
330 TEST_F(QuicEndToEndTest, MLKEMDisabled) {
331 // Disable ML-KEM on the client.
332 base::test::ScopedFeatureList scoped_feature_list;
333 scoped_feature_list.InitWithFeatures({}, {features::kPostQuantumKyber});
334
335 // Configure the server to only support ML-KEM.
336 server_->crypto_config()->set_preferred_groups({SSL_GROUP_X25519_MLKEM768});
337
338 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
339
340 TestTransactionConsumer consumer(DEFAULT_PRIORITY,
341 transaction_factory_.get());
342 consumer.Start(&request_, NetLogWithSource());
343
344 // Connection should fail because there's no supported group in common between
345 // client and server.
346 EXPECT_EQ(consumer.error(), net::ERR_QUIC_PROTOCOL_ERROR);
347 }
348
349 } // namespace test
350 } // namespace net
351