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