1 // Copyright 2017 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 "net/quic/quic_session_pool.h"
6
7 #include <fuzzer/FuzzedDataProvider.h>
8
9 #include <algorithm>
10
11 #include "base/no_destructor.h"
12 #include "base/task/sequenced_task_runner.h"
13 #include "net/base/network_anonymization_key.h"
14 #include "net/base/privacy_mode.h"
15 #include "net/base/proxy_chain.h"
16 #include "net/base/session_usage.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/cert/do_nothing_ct_verifier.h"
19 #include "net/cert/mock_cert_verifier.h"
20 #include "net/cert/x509_certificate.h"
21 #include "net/dns/context_host_resolver.h"
22 #include "net/dns/fuzzed_host_resolver_util.h"
23 #include "net/dns/host_resolver_system_task.h"
24 #include "net/dns/public/secure_dns_policy.h"
25 #include "net/http/http_server_properties.h"
26 #include "net/http/transport_security_state.h"
27 #include "net/quic/mock_crypto_client_stream_factory.h"
28 #include "net/quic/mock_quic_context.h"
29 #include "net/quic/quic_context.h"
30 #include "net/quic/quic_http_stream.h"
31 #include "net/quic/quic_session_key.h"
32 #include "net/quic/test_task_runner.h"
33 #include "net/socket/fuzzed_datagram_client_socket.h"
34 #include "net/socket/fuzzed_socket_factory.h"
35 #include "net/socket/socket_tag.h"
36 #include "net/spdy/multiplexed_session_creation_initiator.h"
37 #include "net/ssl/ssl_config_service_defaults.h"
38 #include "net/test/gtest_util.h"
39 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
40 #include "url/scheme_host_port.h"
41 #include "url/url_constants.h"
42
43 namespace net {
44
45 namespace {
46
47 const uint8_t kCertData[] = {
48 #include "net/data/ssl/certificates/wildcard.inc"
49 };
50
51 } // namespace
52
53 namespace test {
54
55 const char kServerHostName[] = "www.example.org";
56 const int kServerPort = 443;
57 const char kUrl[] = "https://www.example.org/";
58 // TODO(nedwilliamson): Add POST here after testing
59 // whether that can lead blocking while waiting for
60 // the callbacks.
61 const char kMethod[] = "GET";
62 const size_t kBufferSize = 4096;
63 const int kCertVerifyFlags = 0;
64
65 // Persistent factory data, statically initialized on the first time
66 // LLVMFuzzerTestOneInput is called.
67 struct FuzzerEnvironment {
FuzzerEnvironmentnet::test::FuzzerEnvironment68 FuzzerEnvironment()
69 : scheme_host_port(url::kHttpsScheme, kServerHostName, kServerPort) {
70 net::SetSystemDnsResolutionTaskRunnerForTesting( // IN-TEST
71 base::SequencedTaskRunner::GetCurrentDefault());
72
73 quic_context.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
74 ssl_config_service = std::make_unique<SSLConfigServiceDefaults>();
75 crypto_client_stream_factory.set_use_mock_crypter(true);
76 cert_verifier = std::make_unique<MockCertVerifier>();
77 verify_details.cert_verify_result.verified_cert =
78 X509Certificate::CreateFromBytes(kCertData);
79 CHECK(verify_details.cert_verify_result.verified_cert);
80 verify_details.cert_verify_result.is_issued_by_known_root = true;
81 }
82 ~FuzzerEnvironment() = default;
83
84 std::unique_ptr<SSLConfigService> ssl_config_service;
85 ProofVerifyDetailsChromium verify_details;
86 MockCryptoClientStreamFactory crypto_client_stream_factory;
87 url::SchemeHostPort scheme_host_port;
88 NetLogWithSource net_log;
89 std::unique_ptr<CertVerifier> cert_verifier;
90 TransportSecurityState transport_security_state;
91 quic::QuicTagVector connection_options;
92 quic::QuicTagVector client_connection_options;
93 MockQuicContext quic_context;
94 };
95
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)96 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
97 FuzzedDataProvider data_provider(data, size);
98 FuzzerEnvironment env;
99
100 std::unique_ptr<ContextHostResolver> host_resolver =
101 CreateFuzzedContextHostResolver(HostResolver::ManagerOptions(), nullptr,
102 &data_provider,
103 true /* enable_caching */);
104 FuzzedSocketFactory socket_factory(&data_provider);
105
106 // Initialize this on each loop since some options mutate this.
107 HttpServerProperties http_server_properties;
108
109 QuicParams& params = *env.quic_context.params();
110 params.max_server_configs_stored_in_properties =
111 data_provider.ConsumeBool() ? 1 : 0;
112 params.close_sessions_on_ip_change = data_provider.ConsumeBool();
113 params.allow_server_migration = data_provider.ConsumeBool();
114 params.estimate_initial_rtt = data_provider.ConsumeBool();
115 params.enable_socket_recv_optimization = data_provider.ConsumeBool();
116
117 env.crypto_client_stream_factory.AddProofVerifyDetails(&env.verify_details);
118
119 params.goaway_sessions_on_ip_change = false;
120 params.migrate_sessions_early_v2 = false;
121 params.migrate_sessions_on_network_change_v2 = false;
122 params.retry_on_alternate_network_before_handshake = false;
123 params.migrate_idle_sessions = false;
124
125 if (!params.close_sessions_on_ip_change) {
126 params.goaway_sessions_on_ip_change = data_provider.ConsumeBool();
127 if (!params.goaway_sessions_on_ip_change) {
128 params.migrate_sessions_on_network_change_v2 =
129 data_provider.ConsumeBool();
130 if (params.migrate_sessions_on_network_change_v2) {
131 params.migrate_sessions_early_v2 = data_provider.ConsumeBool();
132 params.retry_on_alternate_network_before_handshake =
133 data_provider.ConsumeBool();
134 params.migrate_idle_sessions = data_provider.ConsumeBool();
135 }
136 }
137 }
138
139 std::unique_ptr<QuicSessionPool> factory = std::make_unique<QuicSessionPool>(
140 env.net_log.net_log(), host_resolver.get(), env.ssl_config_service.get(),
141 &socket_factory, &http_server_properties, env.cert_verifier.get(),
142 &env.transport_security_state, nullptr, nullptr, nullptr,
143 &env.crypto_client_stream_factory, &env.quic_context);
144
145 QuicSessionRequest request(factory.get());
146 TestCompletionCallback callback;
147 NetErrorDetails net_error_details;
148 quic::ParsedQuicVersionVector versions = AllSupportedQuicVersions();
149 quic::ParsedQuicVersion version =
150 versions[data_provider.ConsumeIntegralInRange<size_t>(
151 0, versions.size() - 1)];
152
153 quic::QuicEnableVersion(version);
154
155 request.Request(
156 env.scheme_host_port, version, ProxyChain::Direct(),
157 TRAFFIC_ANNOTATION_FOR_TESTS, /*http_user_agent_settings=*/nullptr,
158 SessionUsage::kDestination, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY,
159 SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
160 /*require_dns_https_alpn=*/false, kCertVerifyFlags, GURL(kUrl),
161 env.net_log, &net_error_details,
162 MultiplexedSessionCreationInitiator::kUnknown,
163 /*failed_on_default_network_callback=*/CompletionOnceCallback(),
164 callback.callback());
165
166 callback.WaitForResult();
167 std::unique_ptr<QuicChromiumClientSession::Handle> session =
168 request.ReleaseSessionHandle();
169 if (!session) {
170 return 0;
171 }
172 auto dns_aliases = session->GetDnsAliasesForSessionKey(request.session_key());
173 auto stream = std::make_unique<QuicHttpStream>(std::move(session),
174 std::move(dns_aliases));
175
176 HttpRequestInfo request_info;
177 request_info.method = kMethod;
178 request_info.url = GURL(kUrl);
179 request_info.traffic_annotation =
180 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
181 stream->RegisterRequest(&request_info);
182 stream->InitializeStream(true, DEFAULT_PRIORITY, env.net_log,
183 CompletionOnceCallback());
184
185 HttpResponseInfo response;
186 HttpRequestHeaders request_headers;
187 if (OK !=
188 stream->SendRequest(request_headers, &response, callback.callback())) {
189 return 0;
190 }
191
192 // TODO(nedwilliamson): attempt connection migration here
193 int rv = stream->ReadResponseHeaders(callback.callback());
194 if (rv != OK && rv != ERR_IO_PENDING) {
195 return 0;
196 }
197 callback.WaitForResult();
198
199 auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
200 rv = stream->ReadResponseBody(buffer.get(), kBufferSize, callback.callback());
201 if (rv == ERR_IO_PENDING) {
202 callback.WaitForResult();
203 }
204
205 return 0;
206 }
207
208 } // namespace test
209 } // namespace net
210