Add an initial libfuzzer based fuzzer for the admin console

Run the actual fuzzer like this:

./admin_fuzzer -max_len=16384 fuzzer/admin-data/

Change-Id: I5891df8033ff1837afce86775ee62447587f2f20
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/91504
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
distro/collabora/co-4-2-2
Miklos Vajna 2020-04-01 17:22:23 +02:00
parent 01509b4087
commit a4e0a00bfe
7 changed files with 54 additions and 7 deletions

View File

@ -131,7 +131,9 @@ noinst_PROGRAMS = clientnb \
loolsocketdump
if ENABLE_LIBFUZZER
noinst_PROGRAMS += clientsession_fuzzer
noinst_PROGRAMS += \
admin_fuzzer \
clientsession_fuzzer
else
noinst_PROGRAMS += loolwsd_fuzzer
endif
@ -161,6 +163,16 @@ loolwsd_fuzzer_SOURCES = $(loolwsd_sources) \
$(shared_sources) \
kit/DummyLibreOfficeKit.cpp
admin_fuzzer_CPPFLAGS = \
-DKIT_IN_PROCESS=1 \
$(AM_CPPFLAGS)
admin_fuzzer_SOURCES = \
$(loolwsd_sources) \
$(loolforkit_sources) \
$(shared_sources) \
fuzzer/Admin.cpp
admin_fuzzer_LDFLAGS = -fsanitize=fuzzer $(AM_LDFLAGS)
clientsession_fuzzer_CPPFLAGS = \
-DKIT_IN_PROCESS=1 \
$(AM_CPPFLAGS)

22
fuzzer/Admin.cpp 100644
View File

@ -0,0 +1,22 @@
#include <iostream>
#include "Admin.hpp"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
Admin& admin = Admin::instance();
auto handler = std::make_shared<AdminSocketHandler>(&admin);
std::string input(reinterpret_cast<const char*>(data), size);
std::stringstream ss(input);
std::string line;
while (std::getline(ss, line, '\n'))
{
std::vector<char> lineVector(line.data(), line.data() + line.size());
handler->handleMessage(lineVector);
}
return 0;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -0,0 +1,9 @@
auth jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJsb29sIiwic3ViIjoiYWRtaW4iLCJhdWQiOiJhZG1pbiIsIm5tZSI6ImFkbWluIiwiZXhwIjoiMTU4NTU3ODM1NiJ9.v_VuMvhuUHlcQN-vTzPl3UzIbkmXd5brIVc_RjSa10KjOo9lG6JXw1Jpvin1pbP2Q4QtyQo5o9yGlVW_JdMoA7neeQkq4FwA2MCJzXu9Kp62SB8KVqDkVafNBS4ZV_oGLU8tAjuGDWPC9oZj4H-07j6L9LC3SWbKlLUvdsC5nixXRiijHj6TWP_7HnVrPX1OuaaJM47Q--Wu7_3fI5pj4OLKYzLPX6ONlhO3YQKY1GaVLvIzbRo2J-A0x0KFk_k0JWo6dEtSK3Hr47xxyn3nt1AuyHowgxO8G2IKPGcFjrMcyKS2khh3DGNa5Re21Jm-e3LhtNX-sCpWnXhTuQqBxQ
documents
subscribe adddoc rmdoc resetidle propchange modifications
mem_consumed
active_docs_count
active_users_count
sent_bytes
recv_bytes
uptime

View File

@ -540,7 +540,7 @@ public:
int sendMessage(const char* data, const size_t len, const WSOpCode code, const bool flush = true) const
{
int unitReturn = -1;
if (UnitBase::get().filterSendMessage(data, len, code, flush, unitReturn))
if (!Util::isFuzzing() && UnitBase::get().filterSendMessage(data, len, code, flush, unitReturn))
return unitReturn;
//TODO: Support fragmented messages.

View File

@ -283,7 +283,11 @@ AdminSocketHandler::AdminSocketHandler(Admin* adminManager)
void AdminSocketHandler::sendTextFrame(const std::string& message)
{
UnitWSD::get().onAdminQueryMessage(message);
if (!Util::isFuzzing())
{
UnitWSD::get().onAdminQueryMessage(message);
}
if (_isAuthenticated)
{
LOG_TRC("send admin text frame '" << message << "'");

View File

@ -38,13 +38,13 @@ public:
static void subscribeAsync(const std::shared_ptr<AdminSocketHandler>& handler);
/// Process incoming websocket messages
void handleMessage(const std::vector<char> &data) override;
private:
/// Sends text frames simply to authenticated clients.
void sendTextFrame(const std::string& message);
/// Process incoming websocket messages
void handleMessage(const std::vector<char> &data) override;
private:
Admin* _admin;
int _sessionId;

View File

@ -146,7 +146,7 @@ bool JWTAuth::verify(const std::string& accessToken)
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t curtime = std::chrono::system_clock::to_time_t(now);
if (curtime > decodedExptime)
if (!Util::isFuzzing() && curtime > decodedExptime)
{
LOG_INF("JWTAuth:verify: JWT expired; curtime:" << curtime << ", exp:" << decodedExptime);
return false;