curl-fuzzer C++ reference
Loading...
Searching...
No Matches
h2_proxy_mock_server.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) Max Dymond, <cmeister2@gmail.com>, et al.
3 *
4 * SPDX-License-Identifier: curl
5 */
6
9
11
12#include <curl/curl.h>
13
14#include <algorithm>
15
16#include "proto_fuzzer/tls_test_credentials.h"
17
18namespace proto_fuzzer {
19
25H2ProxyMockServer::H2ProxyMockServer(H2ProxyMode mode, curl::fuzzer::proto::ProxyProtocol protocol)
26 : TlsMockServer(protocol == curl::fuzzer::proto::PROXY_PROTOCOL_HTTP1 ? TlsApplicationProtocol::kHttp11
28 mode_(protocol == curl::fuzzer::proto::PROXY_PROTOCOL_HTTP1 ? H2ProxyMode::kTunnel : mode),
29 protocol_(protocol) {}
30
39
40 // A numeric loopback authority avoids DNS before OPENSOCKETFUNCTION replaces
41 // the transport with its socketpair. The certificate is still verified
42 // against the fixed trust anchor; hostname verification is disabled because
43 // its SAN intentionally names tls.test rather than an IP address.
44 static constexpr char kProxyUrl[] = "https://127.0.0.1:443";
45 struct curl_blob trust_anchor = {const_cast<char*>(tls_test_credentials::kCertificatePem),
46 sizeof(tls_test_credentials::kCertificatePem) - 1, CURL_BLOB_NOCOPY};
47 // The shared baseline maps direct destinations to a loopback sentinel. Once
48 // a proxy is selected that mapping instead rewrites the CONNECT authority,
49 // hiding the scenario's canonical origin from cf-h2-proxy. The proxy socket
50 // remains confined by OPENSOCKETFUNCTION, so detaching CONNECT_TO here is
51 // both safe and necessary for meaningful authority/header coverage.
52 (void)curl_easy_setopt(easy, CURLOPT_CONNECT_TO, nullptr);
53 (void)curl_easy_setopt(easy, CURLOPT_PROXY, kProxyUrl);
54 const long proxy_type = protocol_ == curl::fuzzer::proto::PROXY_PROTOCOL_HTTP1 ? static_cast<long>(CURLPROXY_HTTPS)
55 : static_cast<long>(CURLPROXY_HTTPS2);
56 (void)curl_easy_setopt(easy, CURLOPT_PROXYTYPE, proxy_type);
57 (void)curl_easy_setopt(easy, CURLOPT_NOPROXY, "");
58 (void)curl_easy_setopt(easy, CURLOPT_HTTPPROXYTUNNEL, mode_ == H2ProxyMode::kTunnel ? 1L : 0L);
59 (void)curl_easy_setopt(easy, CURLOPT_PROXY_CAINFO_BLOB, &trust_anchor);
60 (void)curl_easy_setopt(easy, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
61 (void)curl_easy_setopt(easy, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
62}
63
67std::unique_ptr<MockConnection> H2ProxyMockServer::CreateConnection() {
68 std::unique_ptr<MockConnection> connection = TlsMockServer::CreateConnection();
69 if (connection != nullptr) {
70 connection->SetIncomingDataObserver(this);
71 }
72 return connection;
73}
74
76void H2ProxyMockServer::ObserveIncomingData(const unsigned char* data, std::size_t size) {
77 if (data == nullptr || size == 0 || client_transcript_.size() >= scenario_limits::kMaxHttp2ObservedBytes) {
78 return;
79 }
80 const std::size_t remaining = scenario_limits::kMaxHttp2ObservedBytes - client_transcript_.size();
81 client_transcript_.append(reinterpret_cast<const char*>(data), std::min(size, remaining));
82}
83
85const std::string& H2ProxyMockServer::client_transcript() const { return client_transcript_; }
86
87} // namespace proto_fuzzer
H2ProxyMockServer(H2ProxyMode mode=H2ProxyMode::kTunnel, curl::fuzzer::proto::ProxyProtocol protocol=curl::fuzzer::proto::PROXY_PROTOCOL_HTTP2)
Select the closed proxy protocol profile before any connection opens.
void Install(CURL *easy) override
Install the socket transport and force one verified HTTPS proxy.
const std::string & client_transcript() const
std::unique_ptr< MockConnection > CreateConnection() override
Attach a bounded observer after TLS decoding so tests can verify the real CONNECT request rather than...
virtual void Install(CURL *easy)
Install the common OPENSOCKETFUNCTION / OPENSOCKETDATA / SOCKOPTFUNCTION callbacks on 'easy'.
TlsMockServer()
Build one reusable in-process server context per fuzz iteration.
std::unique_ptr< MockConnection > CreateConnection() override
Wrap one socketpair server endpoint in an OpenSSL acceptor consumed by MockServer.
Deterministic HTTPS/HTTP2 proxy for structured scenarios.
H2ProxyMode
Origin-request shape carried by the fixed HTTPS/HTTP2 proxy transport.
@ kTunnel
Establish CONNECT, then carry a plaintext HTTP/1.1 origin exchange.
constexpr std::size_t kMaxHttp2ObservedBytes
Client tracking only needs frame headers and one maximum ordinary payload.
TlsApplicationProtocol
Application protocol selected by the in-process TLS peer.
@ kHttp2
The dedicated proxy peer exchanges HTTP/2 frames after its handshake.
@ kHttp11
Ordinary HTTPS scripts contain HTTP/1.1 response bytes.