2024-10-15 12:41:41 +03:00
|
|
|
// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <iostream>
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
#include <fuzz.h>
|
|
|
|
|
|
|
|
#include <asiolink/io_service.h>
|
|
|
|
#include <asiolink/interval_timer.h>
|
|
|
|
#include <cc/data.h>
|
|
|
|
#include <config/cmd_http_listener.h>
|
2024-10-23 16:40:32 +03:00
|
|
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
|
|
|
#include <dhcpsrv/cfgmgr.h>
|
2024-10-15 12:41:41 +03:00
|
|
|
#include <http/listener.h>
|
|
|
|
#include <http/post_request_json.h>
|
|
|
|
#include <http/response.h>
|
|
|
|
#include <http/response_json.h>
|
|
|
|
#include <http/tests/response_test.h>
|
|
|
|
#include <http/testutils/test_http_client.h>
|
|
|
|
#include <process/d_controller.h>
|
|
|
|
#include <util/filesystem.h>
|
|
|
|
#include <util/multi_threading_mgr.h>
|
|
|
|
|
|
|
|
using namespace isc::asiolink;
|
|
|
|
using namespace isc::config;
|
|
|
|
using namespace isc::data;
|
2024-10-23 16:40:32 +03:00
|
|
|
using namespace isc::dhcp;
|
2024-10-15 12:41:41 +03:00
|
|
|
using namespace isc::process;
|
|
|
|
using namespace isc::http;
|
|
|
|
using namespace isc::http::test;
|
|
|
|
using namespace isc::util;
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2024-10-23 16:40:32 +03:00
|
|
|
static pid_t const PID(getpid());
|
|
|
|
static string const PID_STR(to_string(PID));
|
2024-10-23 10:59:31 +03:00
|
|
|
static string const ADDRESS("::1");
|
2024-10-23 16:40:32 +03:00
|
|
|
static string const KEA_DHCP6_CONF(KEA_FUZZ_DIR + "/kea-dhcp6-" + PID_STR + ".conf");
|
|
|
|
static string const KEA_DHCP6_CSV(KEA_FUZZ_DIR + "/kea-dhcp6-" + PID_STR + ".csv");
|
|
|
|
|
2024-10-23 10:59:31 +03:00
|
|
|
static int PORT;
|
|
|
|
static string PORT_STR;
|
|
|
|
|
2024-10-15 12:41:41 +03:00
|
|
|
/// @brief Represents HTTP POST request with JSON body.
|
|
|
|
///
|
|
|
|
/// In addition to the requirements specified by the @ref PostHttpRequest
|
|
|
|
/// this class requires that the "Content-Type" is "application/json".
|
|
|
|
///
|
|
|
|
/// This class provides methods to parse and retrieve JSON data structures.
|
|
|
|
struct PostHttpRequestBytes : PostHttpRequest {
|
|
|
|
/// @brief Constructor for inbound HTTP request.
|
|
|
|
explicit PostHttpRequestBytes() : PostHttpRequest() {
|
|
|
|
requireHeaderValue("Content-Type", "application/json");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @brief Constructor for outbound HTTP request.
|
|
|
|
///
|
|
|
|
/// This constructor adds "Content-Type" header with the value of
|
|
|
|
/// "application/json" to the context.
|
|
|
|
///
|
|
|
|
/// @param method HTTP method, e.g. POST.
|
|
|
|
/// @param uri URI.
|
|
|
|
/// @param version HTTP version.
|
|
|
|
/// @param host_header Host header to be included in the request. The default
|
|
|
|
/// is the empty Host header.
|
|
|
|
/// @param basic_auth Basic HTTP authentication credential. The default
|
|
|
|
/// is no authentication.
|
|
|
|
explicit PostHttpRequestBytes(const Method& method,
|
|
|
|
const string& uri,
|
|
|
|
const HttpVersion& version,
|
|
|
|
const HostHttpHeader& host_header = HostHttpHeader(),
|
|
|
|
const BasicHttpAuthPtr& basic_auth = BasicHttpAuthPtr())
|
|
|
|
: PostHttpRequest(method, uri, version, host_header, basic_auth) {
|
|
|
|
requireHeaderValue("Content-Type", "application/json");
|
|
|
|
context()->headers_.push_back(HttpHeaderContext("Content-Type", "application/json"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @brief Sets JSON body for an outbound message.
|
|
|
|
///
|
|
|
|
/// @param body JSON structure to be used as a body.
|
|
|
|
void setBodyAsBytes(vector<uint8_t> const& input) {
|
|
|
|
context_->body_ = string(input.begin(), input.end());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
using PostHttpRequestBytesPtr = boost::shared_ptr<PostHttpRequestBytes>;
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
int
|
|
|
|
LLVMFuzzerInitialize() {
|
|
|
|
static bool initialized(DoInitialization());
|
|
|
|
assert(initialized);
|
|
|
|
|
2024-10-23 10:59:31 +03:00
|
|
|
setenv("KEA_DHCP6_FUZZING_ROTATE_PORT", "true", 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
LLVMFuzzerTearDown() {
|
|
|
|
try {
|
|
|
|
remove(KEA_DHCP6_CONF.c_str());
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
remove(KEA_DHCP6_CSV.c_str());
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) {
|
|
|
|
CfgMgr::instance().clear();
|
|
|
|
ControlledDhcpv6Srv server;
|
|
|
|
|
|
|
|
PORT = ControlledDhcpv6Srv::getInstance()->getServerPort();
|
|
|
|
PORT_STR = to_string(PORT);
|
|
|
|
|
2024-10-23 16:40:32 +03:00
|
|
|
writeToFile(KEA_DHCP6_CONF, R"(
|
|
|
|
{
|
|
|
|
"Dhcp6": {
|
|
|
|
"control-sockets": [
|
|
|
|
{
|
2024-10-22 17:39:57 +03:00
|
|
|
"socket-address": ")" + ADDRESS + R"(",
|
2024-10-23 16:40:32 +03:00
|
|
|
"socket-port": )" + PORT_STR + R"(,
|
|
|
|
"socket-type": "http"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"lease-database": {
|
|
|
|
"name": ")" + KEA_DHCP6_CSV + R"(",
|
2024-10-22 17:39:57 +03:00
|
|
|
"persist": false,
|
2024-10-23 16:40:32 +03:00
|
|
|
"type": "memfile"
|
|
|
|
},
|
|
|
|
"server-id": {
|
|
|
|
"type": "EN",
|
|
|
|
"enterprise-id": 2495,
|
|
|
|
"identifier": "0123456789",
|
|
|
|
"persist": false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)");
|
|
|
|
|
|
|
|
server.init(KEA_DHCP6_CONF);
|
|
|
|
|
2024-10-22 17:39:57 +03:00
|
|
|
HttpClient client(ControlledDhcpv6Srv::getInstance()->getIOService(), false);
|
2024-10-15 12:41:41 +03:00
|
|
|
stringstream ss;
|
2024-10-22 17:39:57 +03:00
|
|
|
ss << "http://[" << ADDRESS << "]:" << PORT_STR;
|
2024-10-15 12:41:41 +03:00
|
|
|
Url url(ss.str());
|
|
|
|
|
|
|
|
// Initiate request to the server.
|
|
|
|
PostHttpRequestBytesPtr request(new PostHttpRequestBytes(
|
|
|
|
HttpRequest::Method::HTTP_POST, "/", HttpVersion(1, 1)));
|
|
|
|
|
|
|
|
// Body is a map with a specified parameter included.
|
|
|
|
vector<uint8_t> const body(data, data + size);
|
|
|
|
request->setBodyAsBytes(body);
|
|
|
|
request->finalize();
|
|
|
|
HttpResponseJsonPtr response(new HttpResponseJson());
|
|
|
|
client.asyncSendRequest(
|
|
|
|
url, TlsContextPtr(), request, response,
|
|
|
|
[](boost::system::error_code const&,
|
|
|
|
HttpResponsePtr const&,
|
|
|
|
string const&) {
|
|
|
|
});
|
|
|
|
|
2024-10-22 17:39:57 +03:00
|
|
|
ControlledDhcpv6Srv::getInstance()->getIOService()->poll();
|
2024-10-15 12:41:41 +03:00
|
|
|
|
|
|
|
// Make sure that the received responses are different. We check that by
|
|
|
|
// comparing value of the sequence parameters.
|
|
|
|
if (getenv("DEBUG")) {
|
|
|
|
if (response) {
|
|
|
|
cout << response->getBody() << endl;
|
|
|
|
} else {
|
|
|
|
cout << "no response" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
client.stop();
|
2024-10-22 17:39:57 +03:00
|
|
|
ControlledDhcpv6Srv::getInstance()->getIOService()->poll();
|
2024-10-15 12:41:41 +03:00
|
|
|
MultiThreadingMgr::instance().setMode(false);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // extern "C"
|