curl-fuzzer C++ reference
Loading...
Searching...
No Matches
socks4_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#include <cstddef>
16#include <memory>
17
18namespace proto_fuzzer {
19
20namespace {
21
22long ProxyType(curl::fuzzer::proto::SocksProxyMode mode) {
23 switch (mode) {
24 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS4A:
25 return CURLPROXY_SOCKS4A;
26 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS5:
27 return CURLPROXY_SOCKS5;
28 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS5_HOSTNAME:
29 return CURLPROXY_SOCKS5_HOSTNAME;
30 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS4:
31 default:
32 return CURLPROXY_SOCKS4;
33 }
34}
35
36const char* ProxyUrl(curl::fuzzer::proto::SocksProxyMode mode) {
37 switch (mode) {
38 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS4A:
39 return "socks4a://127.0.0.1:1080";
40 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS5:
41 return "socks5://127.0.0.1:1080";
42 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS5_HOSTNAME:
43 return "socks5h://127.0.0.1:1080";
44 case curl::fuzzer::proto::SOCKS_PROXY_SOCKS4:
45 default:
46 return "socks4://127.0.0.1:1080";
47 }
48}
49
50} // namespace
51
58ProxyTransportMockServer::ProxyTransportMockServer(curl::fuzzer::proto::SocksProxyMode mode, bool haproxy_protocol)
59 : mode_(mode), haproxy_protocol_(haproxy_protocol) {}
60
65 client_transcript_.clear();
66
67 // CONNECT_TO applies to the origin and would replace the hostname that the
68 // SOCKS request is meant to exercise. The numeric proxy cannot require DNS,
69 // while OPENSOCKETFUNCTION still replaces its outbound socket with the
70 // in-process peer.
71 static constexpr char kProxyUser[] = "fuzz-user";
72 static constexpr char kProxyPassword[] = "fuzz-pass";
73 static constexpr char kHaproxyClientIp[] = "127.0.0.1";
74 (void)curl_easy_setopt(easy, CURLOPT_CONNECT_TO, nullptr);
75 (void)curl_easy_setopt(easy, CURLOPT_PROXY, ProxyUrl(mode_));
76 (void)curl_easy_setopt(easy, CURLOPT_PROXYTYPE, ProxyType(mode_));
77 (void)curl_easy_setopt(easy, CURLOPT_NOPROXY, "");
78 (void)curl_easy_setopt(easy, CURLOPT_PROXYUSERNAME, kProxyUser);
79 (void)curl_easy_setopt(easy, CURLOPT_PROXYPASSWORD, kProxyPassword);
80 // Advertise no-auth plus username/password only. This keeps the client hello
81 // deterministic while letting the scripted method-selection response enter
82 // either SOCKS5 branch.
83 (void)curl_easy_setopt(easy, CURLOPT_SOCKS5_AUTH, static_cast<long>(CURLAUTH_BASIC));
84 // The locally resolved SOCKS5 mode must be deterministic across hosts that
85 // expose both ::1 and 127.0.0.1 for localhost.
86 (void)curl_easy_setopt(easy, CURLOPT_IPRESOLVE, static_cast<long>(CURL_IPRESOLVE_V4));
87 (void)curl_easy_setopt(easy, CURLOPT_HAPROXY_CLIENT_IP, haproxy_protocol_ ? kHaproxyClientIp : nullptr);
88 (void)curl_easy_setopt(easy, CURLOPT_HAPROXYPROTOCOL, haproxy_protocol_ ? 1L : 0L);
89}
90
92const std::string& ProxyTransportMockServer::client_transcript() const { return client_transcript_; }
93
96std::unique_ptr<MockConnection> ProxyTransportMockServer::CreateConnection() {
97 auto connection = std::make_unique<MockConnection>();
98 connection->SetIncomingDataObserver(this);
99 return connection;
100}
101
104
108void ProxyTransportMockServer::ObserveIncomingData(const unsigned char* data, std::size_t size) {
109 if (data == nullptr || size == 0 || client_transcript_.size() >= kMaxTranscriptBytes) {
110 return;
111 }
112 const std::size_t remaining = kMaxTranscriptBytes - client_transcript_.size();
113 client_transcript_.append(reinterpret_cast<const char*>(data), std::min(size, remaining));
114}
115
118#if defined(PROTO_FUZZER_OBSERVE_STATE)
120 const volatile std::size_t proxy_observation = client_transcript().size();
121 (void)proxy_observation;
122#endif
123}
124
125} // namespace proto_fuzzer
virtual void Install(CURL *easy)
Install the common OPENSOCKETFUNCTION / OPENSOCKETDATA / SOCKOPTFUNCTION callbacks on 'easy'.
virtual void ObserveState()
Default no-op for peers without protocol-specific observations.
const std::string & client_transcript() const
void ObserveState() override
Retain protocol outcomes in coverage and introspector builds.
void ObserveIncomingData(const unsigned char *data, std::size_t size) override
Retain a bounded prefix of client bytes for strict integration tests.
ProxyTransportMockServer(curl::fuzzer::proto::SocksProxyMode mode, bool haproxy_protocol)
Select a fixed SOCKS wire version, resolution side, and optional HAProxy prefix.
void Install(CURL *easy) override
Install common socket callbacks and the fixed SOCKS proxy policy.
std::unique_ptr< MockConnection > CreateConnection() override
Create one socketpair peer and attach the raw-byte transcript observer.
Deterministic SOCKS/HAProxy transport for HTTP scenarios.