curl-fuzzer C++ reference
Loading...
Searching...
No Matches
proto_fuzzer::LdapMockServer Class Reference

Services curl's single-connection LDAP bind and search exchange. More...

#include <ldap_mock_server.h>

Inheritance diagram for proto_fuzzer::LdapMockServer:
proto_fuzzer::MockServerBase proto_fuzzer::IncomingDataObserver proto_fuzzer::LdapsMockServer

Public Member Functions

 LdapMockServer ()
 Begin without a borrowed protobuf or open socketpair.
 ~LdapMockServer () override
 Release the server-owned socketpair half after curl has returned its client descriptor.
void ObserveState () override
 Retain protocol outcomes in coverage and introspector builds.
void ObserveIncomingData (const unsigned char *data, std::size_t size) override
 Append one fragment after the transport has decoded it.
const std::string & packet_transcript () const
std::size_t bind_request_count () const
std::size_t search_request_count () const
std::size_t mechanism_search_request_count () const
std::size_t starttls_request_count () const
std::size_t unbind_request_count () const
std::size_t server_message_count () const
std::size_t scripted_message_count () const
std::size_t synthesized_done_count () const
std::size_t scripted_bind_response_count () const
Public Member Functions inherited from proto_fuzzer::MockServerBase
virtual ~MockServerBase ()
 Out-of-line destructor so MockConnection can stay forward-declared in the base header (its complete type is only needed where unique_ptr is instantiated for destruction).
virtual void Install (CURL *easy)
 Install the common OPENSOCKETFUNCTION / OPENSOCKETDATA / SOCKOPTFUNCTION callbacks on 'easy'.
virtual void ConfigureRequestData (ScenarioRequestData *request_data)
 Bind protocol-specific work to the request-data callbacks after their per-scenario state has been constructed.
CURLcode DriveScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario)
 Run 'scenario' to completion on 'easy': allocate a multi, attach 'easy', delegate protocol-specific work to RunLoop, consume its completion message, and clean up.
virtual CURLcode DriveEasyScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario, bool use_events=false)
 Run through the public easy entrypoint when a protocol mock can preload all peer work before curl takes control.
virtual ConnectOnlyRunStats DriveConnectOnlyScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario)
 Establish a CONNECT_ONLY transport, then perform bounded direct I/O.
void SetMultiObserver (MultiObserver observer)
 Register an observer invoked with the live multi handle after 'easy' is attached and before the drive loop starts.
MockConnection * connection ()

Protected Member Functions

curl_socket_t HandleOpenSocket (curlsocktype purpose=CURLSOCKTYPE_IPCXN, struct curl_sockaddr *address=nullptr) override
 Create the single LDAP socketpair.
virtual std::unique_ptr< MockConnection > CreateConnection ()
 Create the default plaintext transport.
void RunLoop (CURLM *multi, CURL *easy, const curl::fuzzer::proto::Scenario &scenario) override
 Alternate curl transitions with immediate peer service until the transfer completes or deterministic idle/operation caps win.
Protected Member Functions inherited from proto_fuzzer::MockServerBase
 MockServerBase (MultiDrivePolicy drive_policy=MultiDrivePolicy::kPerform)
 Construct an empty base instance with a fixed multi-drive policy.
virtual void HandleDetachedMulti (CurlMultiPtr multi)
 Dispose of or retain the multi after its easy handle has been removed.
virtual SocketSetupDisposition GetSocketSetupDisposition (curl_socket_t curlfd, curlsocktype purpose) const
 Describe the socket returned by HandleOpenSocket without issuing native descriptor queries.
MultiSocketDriver * multi_socket_driver ()
 Expose the callback state installed for the current socket-action drive.
std::size_t additional_handle_cleanup_count () const
void ResumeResponseIfRequested (CURL *easy)
 Resume receive-side callback output at one bounded drive boundary when the dedicated API plan requested it.
void ApplyPendingBackpressure ()
 Apply the BackpressureConfig cached by DriveScenario to the new connection_.

Additional Inherited Members

Public Types inherited from proto_fuzzer::MockServerBase
using MultiObserver = std::function<void(CURLM*)>
 Callback type used to publish the driving multi handle to observers.
Static Protected Member Functions inherited from proto_fuzzer::MockServerBase
static int WaitOnMultiFdset (CURLM *multi, CURLMcode *rc)
 Wait on curl's fdset with a short timeout.
static void ProbeMultiPollset (CURLM *multi)
 Ask curl to construct and inspect its connection-filter pollset without waiting.
static bool MultiPollsetWantsWrite (CURLM *multi, curl_socket_t socket)
 Inspect one socket's current writable interest through curl's public multi fdset API.
static bool UsesTimedDrive (const curl::fuzzer::proto::Scenario &scenario)
 Treat a non-default BackpressureConfig as an explicit request for the slower, timed drive policy.
Protected Attributes inherited from proto_fuzzer::MockServerBase
std::unique_ptr< MockConnection > connection_
 The per-scenario MockConnection, lazily created by HandleOpenSocket().
int pending_recv_buf_bytes_
 Cached SO_RCVBUF/SO_SNDBUF setting in bytes.
std::size_t pending_drain_limit_
 Cached per-call DrainIncoming byte budget.
MultiSocketDriver * multi_socket_driver_
 Non-owning pointer into DriveScenario's stack.
std::size_t additional_handle_cleanup_count_
 Number of application-created handles, excluding the caller's parent, successfully removed from the current multi and cleaned up.
bool resume_response_
 True only for an API-plan multi drive with its one-shot write callback.
MultiObserver multi_observer_
 Observer receiving the live multi handle at the start of a drive.
Static Protected Attributes inherited from proto_fuzzer::MockServerBase
static constexpr int kMaxDriveIterations = 512
 Hard operation budget for one scenario.
static constexpr int kMaxIdleIterations = 8
 Consecutive no-progress budget for ordinary scenarios.
static constexpr int kMaxTimedIdleIterations = 256
 Explicit backpressure scenarios get a larger idle budget and may use the short timed wait above.

Detailed Description

Services curl's single-connection LDAP bind and search exchange.

LDAP is not line-oriented: every message is a BER-encoded LDAPMessage (RFC 4511), so this peer treats Scenario.connection as a binary script. It parses each complete client TLV, answers bind requests with a bindResponse that echoes the client's message id, and replays the scenario's on_readable chunks as search-result messages before synthesizing a searchResDone.

Socket confinement: curl's LDAP handler opens its transport through the ordinary connection filter (and therefore the harness OPENSOCKETFUNCTION), then duplicates that descriptor for OpenLDAP's own socket I/O. Because the duplicate names the same socketpair endpoint, every byte still stays inside the in-process peer; no loopback listener or real network socket is needed.

Transport selection: subclasses replace CreateConnection(). The implicit-TLS LDAPS peer uses that hook to run the identical BER exchange inside a verified OpenSSL acceptor. Incoming application bytes arrive through ObserveIncomingData() after any transport decoding, so the parser does not depend on whether the socketpair is plaintext or TLS.

Script semantics:

  • initial_response, when non-empty, is the bind reply. The peer releases it only after the client's bindRequest and rewrites its envelope messageID to match, so a seed can script both success and failure without hard-coding OpenLDAP's message counter. When empty, the peer synthesizes a successful bindResponse.
  • Before any bind, OpenLDAP's exact root-DSE supportedSASLMechanisms query receives a peer-owned entry advertising only PLAIN and a successful done. This discovery exchange never consumes mutation-controlled result chunks.
  • Each on_readable chunk is one complete server LDAPMessage (for example a searchResEntry). Chunks are forwarded in order after the searchRequest and are renumbered to the search message id when their envelope parses.
  • A chunk carrying searchResDone ends the search. Otherwise the peer writes a successful searchResDone once every chunk has been released.
  • An empty chunk half-closes the peer, preserving a deterministic truncated-stream path instead of inventing a completion.

BER scope: this is intentionally a minimal encoder/decoder. It understands definite-length, one-byte and long-form lengths up to four bytes, and the primitive tags needed to delimit LDAPMessage envelopes and recognize the fixed mechanism query. Scripted server operation bodies remain opaque so malformed server data still reaches OpenLDAP's full parser. All sizes are bounded by kMaxClientMessageBytes.

Definition at line 72 of file ldap_mock_server.h.

Constructor & Destructor Documentation

◆ LdapMockServer()

proto_fuzzer::LdapMockServer::LdapMockServer ( )

Begin without a borrowed protobuf or open socketpair.

RunLoop borrows a Scenario only for the synchronous DriveScenario call in which socket callbacks can run.

Definition at line 56 of file ldap_mock_server.cc.

◆ ~LdapMockServer()

proto_fuzzer::LdapMockServer::~LdapMockServer ( )
overridedefault

Release the server-owned socketpair half after curl has returned its client descriptor.

The out-of-line destructor keeps MockConnection's complete type local to this translation unit.

Member Function Documentation

◆ bind_request_count()

std::size_t proto_fuzzer::LdapMockServer::bind_request_count ( ) const
Returns
Number of bindRequest messages observed.

Definition at line 99 of file ldap_mock_server.cc.

◆ CreateConnection()

std::unique_ptr< MockConnection > proto_fuzzer::LdapMockServer::CreateConnection ( )
protectedvirtual

Create the default plaintext transport.

The LDAPS subclass overrides this factory, which keeps every BER handling path identical across carriers.

Returns
Newly allocated in-process socketpair peer.

Reimplemented in proto_fuzzer::LdapsMockServer.

Definition at line 507 of file ldap_mock_server.cc.

◆ HandleOpenSocket()

curl_socket_t proto_fuzzer::LdapMockServer::HandleOpenSocket ( curlsocktype purpose = CURLSOCKTYPE_IPCXN,
struct curl_sockaddr * address = nullptr )
overrideprotectedvirtual

Create the single LDAP socketpair.

The bind reply is deliberately not queued here: LDAP is client-first, and releasing the scripted reply only after the bindRequest lets the peer rewrite its messageID to OpenLDAP's current counter.

Parameters
purposeSocket role requested by curl.
addressUnused stream destination metadata required by the callback signature.
Returns
Client descriptor for the LDAP channel, or CURL_SOCKET_BAD.

Implements proto_fuzzer::MockServerBase.

Definition at line 517 of file ldap_mock_server.cc.

◆ mechanism_search_request_count()

std::size_t proto_fuzzer::LdapMockServer::mechanism_search_request_count ( ) const
Returns
Number of root-DSE supportedSASLMechanisms searches observed.

Definition at line 105 of file ldap_mock_server.cc.

◆ ObserveIncomingData()

void proto_fuzzer::LdapMockServer::ObserveIncomingData ( const unsigned char * data,
std::size_t size )
overridevirtual

Append one fragment after the transport has decoded it.

Plaintext peers report socket bytes directly; the LDAPS peer reports decrypted application bytes, so the BER parser is independent of the carrier.

Parameters
dataFirst byte of the fragment.
sizeNumber of bytes available at data.

Implements proto_fuzzer::IncomingDataObserver.

Definition at line 91 of file ldap_mock_server.cc.

◆ packet_transcript()

const std::string & proto_fuzzer::LdapMockServer::packet_transcript ( ) const
Returns
A prefix of complete client LDAPMessages from the most recent drive.

Definition at line 84 of file ldap_mock_server.cc.

◆ RunLoop()

void proto_fuzzer::LdapMockServer::RunLoop ( CURLM * multi,
CURL * easy,
const curl::fuzzer::proto::Scenario & scenario )
overrideprotectedvirtual

Alternate curl transitions with immediate peer service until the transfer completes or deterministic idle/operation caps win.

No select(), poll(), or sleep is needed: OpenLDAP reads through a duplicate of the same in-process socketpair endpoint that curl opened, so the peer can answer requests synchronously from this thread.

Parameters
multiMulti handle containing easy.
easyEasy handle already installed on this mock.
scenarioConnection script to borrow.

Implements proto_fuzzer::MockServerBase.

Definition at line 788 of file ldap_mock_server.cc.

◆ scripted_bind_response_count()

std::size_t proto_fuzzer::LdapMockServer::scripted_bind_response_count ( ) const
Returns
Number of bind replies taken from initial_response.

Definition at line 123 of file ldap_mock_server.cc.

◆ scripted_message_count()

std::size_t proto_fuzzer::LdapMockServer::scripted_message_count ( ) const
Returns
Number of scripted search-result chunks forwarded.

Definition at line 117 of file ldap_mock_server.cc.

◆ search_request_count()

std::size_t proto_fuzzer::LdapMockServer::search_request_count ( ) const
Returns
Number of searchRequest messages observed.

Definition at line 102 of file ldap_mock_server.cc.

◆ server_message_count()

std::size_t proto_fuzzer::LdapMockServer::server_message_count ( ) const
Returns
Number of server messages written in the most recent drive.

Definition at line 114 of file ldap_mock_server.cc.

◆ starttls_request_count()

std::size_t proto_fuzzer::LdapMockServer::starttls_request_count ( ) const
Returns
Number of StartTLS ExtendedRequest messages observed.

Definition at line 108 of file ldap_mock_server.cc.

◆ synthesized_done_count()

std::size_t proto_fuzzer::LdapMockServer::synthesized_done_count ( ) const
Returns
Number of searchResDone messages generated by the peer.

Definition at line 120 of file ldap_mock_server.cc.

◆ unbind_request_count()

std::size_t proto_fuzzer::LdapMockServer::unbind_request_count ( ) const
Returns
Number of unbindRequest messages observed.

Definition at line 111 of file ldap_mock_server.cc.


The documentation for this class was generated from the following files: