blob: 026d5a47d2c597098219dc04a69f584c5d1b49ed [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/quic/chromium/quic_stream_factory.h"
#include "base/test/fuzzed_data_provider.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
#include "net/dns/fuzzed_host_resolver.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/transport_security_state.h"
#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/quic_http_stream.h"
#include "net/quic/chromium/test_task_runner.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/socket/fuzzed_datagram_client_socket.h"
#include "net/socket/fuzzed_socket_factory.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h"
namespace net {
namespace {
class MockSSLConfigService : public SSLConfigService {
public:
MockSSLConfigService() {}
void GetSSLConfig(SSLConfig* config) override { *config = config_; }
private:
~MockSSLConfigService() override {}
SSLConfig config_;
};
} // namespace
namespace test {
const char kServerHostName[] = "www.example.org";
const int kServerPort = 443;
const char kUrl[] = "https://www.example.org/";
// TODO(nedwilliamson): Add POST here after testing
// whether that can lead blocking while waiting for
// the callbacks.
const char kMethod[] = "GET";
const size_t kBufferSize = 4096;
const int kCertVerifyFlags = 0;
// Static initialization for persistent factory data
struct Env {
Env() : host_port_pair(kServerHostName, kServerPort), random_generator(0) {
clock.AdvanceTime(QuicTime::Delta::FromSeconds(1));
ssl_config_service = new MockSSLConfigService;
crypto_client_stream_factory.set_use_mock_crypter(true);
cert_verifier = CertVerifier::CreateDefault();
channel_id_service =
std::make_unique<ChannelIDService>(new DefaultChannelIDStore(nullptr));
cert_transparency_verifier = std::make_unique<MultiLogCTVerifier>();
}
MockClock clock;
scoped_refptr<SSLConfigService> ssl_config_service;
MockCryptoClientStreamFactory crypto_client_stream_factory;
HostPortPair host_port_pair;
MockRandom random_generator;
NetLogWithSource net_log;
std::unique_ptr<CertVerifier> cert_verifier;
std::unique_ptr<ChannelIDService> channel_id_service;
TransportSecurityState transport_security_state;
QuicTagVector connection_options;
QuicTagVector client_connection_options;
std::unique_ptr<CTVerifier> cert_transparency_verifier;
CTPolicyEnforcer ct_policy_enforcer;
};
static struct Env* env = new Env();
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
base::FuzzedDataProvider data_provider(data, size);
FuzzedHostResolver host_resolver(HostResolver::Options(), nullptr,
&data_provider);
FuzzedSocketFactory socket_factory(&data_provider);
// Initialize this on each loop since some options mutate this.
HttpServerPropertiesImpl http_server_properties;
std::unique_ptr<QuicStreamFactory> factory =
std::make_unique<QuicStreamFactory>(
env->net_log.net_log(), &host_resolver, env->ssl_config_service.get(),
&socket_factory, &http_server_properties, env->cert_verifier.get(),
&env->ct_policy_enforcer, env->channel_id_service.get(),
&env->transport_security_state, env->cert_transparency_verifier.get(),
nullptr, &env->crypto_client_stream_factory, &env->random_generator,
&env->clock, kDefaultMaxPacketSize, std::string(),
data_provider.ConsumeBool(), data_provider.ConsumeBool(),
kIdleConnectionTimeoutSeconds, kPingTimeoutSecs,
data_provider.ConsumeBool(), data_provider.ConsumeBool(),
data_provider.ConsumeBool(), data_provider.ConsumeBool(),
data_provider.ConsumeBool(), data_provider.ConsumeBool(),
env->connection_options, env->client_connection_options,
data_provider.ConsumeBool());
QuicStreamRequest request(factory.get());
TestCompletionCallback callback;
NetErrorDetails net_error_details;
request.Request(env->host_port_pair,
data_provider.PickValueInArray(kSupportedTransportVersions),
PRIVACY_MODE_DISABLED, kCertVerifyFlags, GURL(kUrl), kMethod,
env->net_log, &net_error_details, callback.callback());
callback.WaitForResult();
std::unique_ptr<QuicChromiumClientSession::Handle> session =
request.ReleaseSessionHandle();
if (!session)
return 0;
std::unique_ptr<HttpStream> stream(new QuicHttpStream(std::move(session)));
HttpRequestInfo request_info;
request_info.method = kMethod;
request_info.url = GURL(kUrl);
stream->InitializeStream(&request_info, DEFAULT_PRIORITY, env->net_log,
CompletionCallback());
HttpResponseInfo response;
HttpRequestHeaders request_headers;
if (OK !=
stream->SendRequest(request_headers, &response, callback.callback()))
return 0;
// TODO(nedwilliamson): attempt connection migration here
stream->ReadResponseHeaders(callback.callback());
callback.WaitForResult();
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kBufferSize);
int rv =
stream->ReadResponseBody(buffer.get(), kBufferSize, callback.callback());
if (rv == ERR_IO_PENDING)
callback.WaitForResult();
return 0;
}
} // namespace test
} // namespace net