diff --git a/test/fuzzing/examples/fuzz-channel-request.cpp b/test/fuzzing/examples/fuzz-channel-request.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03203b308dd0f57085719bdeec06288c7157a353 --- /dev/null +++ b/test/fuzzing/examples/fuzz-channel-request.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> +#include <set> + +#include <msgpack.hpp> + +#include "jamidht/multiplexed_socket.h" + +#include "lib/gnutls.h" + +enum class ChannelRequestState { + REQUEST, + ACCEPT, + DECLINE, +}; + +/** + * That msgpack structure is used to request a new channel (id, name) + * Transmitted over the TLS socket + */ +struct ChannelRequest +{ + std::string name {}; + uint16_t channel {0}; + ChannelRequestState state {ChannelRequestState::REQUEST}; + MSGPACK_DEFINE(name, channel, state) +}; + + + +/* + * Mangle channel + */ +bool +mutate_gnutls_record_send(ChanneledMessage& msg) +{ + try { + msgpack::unpacked result; + msgpack::unpack(result, (const char*) msg.data.data(), msg.data.size(), 0); + auto object = result.get(); + auto req = object.as<ChannelRequest>(); + + int state = rand() % 8; + + static_assert(sizeof(state) == sizeof(req.state)); + memcpy(&req.state, &state, sizeof(state)); + + msgpack::sbuffer buffer(512); + msgpack::pack(buffer, req); + + msg.data.clear(); + + for (size_t i=0; i<buffer.size(); ++i) { + msg.data.emplace_back(buffer.data()[i]); + } + + } catch (...) { + return false; + } + + return true; +} + +MSGPACK_ADD_ENUM(ChannelRequestState); diff --git a/test/fuzzing/examples/fuzz-channel.cpp b/test/fuzzing/examples/fuzz-channel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6286c29be232485dfe5204a082db7c7470c7e91a --- /dev/null +++ b/test/fuzzing/examples/fuzz-channel.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> +#include <set> + +#include "jamidht/multiplexed_socket.h" + +#include "lib/gnutls.h" + +#if 0 +static std::set<uint16_t> known_channel {}; +static std::vector<channel + +__attribute__((constructor)) +static void channel_spammer(void) +{ + std::thread([&]{ + + std::unique_lock<std::mutex> ulock(spammer_lock); + while (true) { + + } + + }).detach(); +} + + +/* + * Mangle channel + */ +bool +mutate_gnutls_record_recv(ChanneledMessage& msg) +{ + known_channel.emplace(msg.channel); + + auto it = known_channel.begin(); + + std::advance(it, rand() % known_channel.size()); + + msg.channel = *it; + + return true; +} +#endif diff --git a/test/fuzzing/examples/fuzz-echo.cpp b/test/fuzzing/examples/fuzz-echo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b2cc71835872825cc6bb95accdb48d59652ac1e2 --- /dev/null +++ b/test/fuzzing/examples/fuzz-echo.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* Do Nothing */ diff --git a/test/fuzzing/examples/fuzz-jami-version.cpp b/test/fuzzing/examples/fuzz-jami-version.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bfb797213ea44d793a5ad1389d2acf56501e14a --- /dev/null +++ b/test/fuzzing/examples/fuzz-jami-version.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <atomic> +#include <chrono> +#include <condition_variable> +#include <mutex> +#include <memory> +#include <thread> + +#include "lib/gnutls.h" + +/* Jami */ +#include "jamidht/multiplexed_socket.h" + +static gnutls_session_t captured_session = nullptr; + +static std::mutex worker_lock {}; +static std::condition_variable cv; + +struct VersionMsg +{ + int v; + MSGPACK_DEFINE_MAP(v) +}; + +__attribute__((constructor)) +static void +init(void) +{ + std::thread([&] { + + msgpack::sbuffer buffer(8); + { + msgpack::packer<msgpack::sbuffer> pk(&buffer); + pk.pack(VersionMsg {rand()}); + } + + msgpack::sbuffer buffer2(16 + buffer.size()); + { + msgpack::packer<msgpack::sbuffer> pk(&buffer2); + pk.pack_array(2); + pk.pack(jami::PROTOCOL_CHANNEL); + pk.pack_bin(buffer2.size()); + pk.pack_bin_body(buffer2.data(), buffer2.size()); + } + + std::unique_lock<std::mutex> lock(worker_lock); + + cv.wait(lock); + + while (true) { + gnutls_record_send(captured_session, buffer2.data(), buffer2.size()); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + + }).detach(); +} + +void +post_gnutls_init_hook(const gnutls_session_t session) +{ + if (nullptr == captured_session) { + captured_session = session; + cv.notify_one(); + } +} diff --git a/test/fuzzing/examples/fuzz-libfuzz.cpp b/test/fuzzing/examples/fuzz-libfuzz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb1994a66da9de67e47fec442b52df4d7c02257c --- /dev/null +++ b/test/fuzzing/examples/fuzz-libfuzz.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "lib/gnutls.h" + +static gnutls_session_t captured_tls_session = nullptr; + + + +void post_gnutls_init_hook(const gnutls_session_t session) +{ + captured_tls_session = session; +} diff --git a/test/fuzzing/examples/fuzz-msgpack.cpp b/test/fuzzing/examples/fuzz-msgpack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23d0585bb44f8ece9cdfb261575240211a3c92d1 --- /dev/null +++ b/test/fuzzing/examples/fuzz-msgpack.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "lib/gnutls.h" +#include "lib/syslog.h" + +/* + * Reverse channel and data in packed message + */ +void +pack_gnutls_record_recv(msgpack::sbuffer& buf, const ChanneledMessage& msg) +{ + msgpack::packer<msgpack::sbuffer> pk(&buf); +#if 0 + pk.pack_array(2); + pk.pack_bin(msg.data.size()); + pk.pack_bin_body((const char*) msg.data.data(), msg.data.size()); + pk.pack(msg.channel); +#else + pk.pack_array(1); + pk.pack(msg.channel); +#endif +} + +bool +mutate_gnutls_record_recv(ChanneledMessage& msg) +{ + (void)msg; + + return true; +} diff --git a/test/fuzzing/examples/fuzz-random-over-tls.cpp b/test/fuzzing/examples/fuzz-random-over-tls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d9809508f52b62d1246ba87b1c64df930973244 --- /dev/null +++ b/test/fuzzing/examples/fuzz-random-over-tls.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <atomic> +#include <chrono> +#include <condition_variable> +#include <mutex> +#include <memory> +#include <thread> + +#include "lib/gnutls.h" + +static gnutls_session_t captured_session = nullptr; + +static std::mutex worker_lock {}; +static std::condition_variable cv {}; + +__attribute__((constructor)) +static void +init(void) +{ + std::thread([&] { + + std::unique_lock<std::mutex> lock(worker_lock); + + cv.wait(lock); + + + size_t max_size = gnutls_record_get_max_size(captured_session); + void *payload = NULL; + + while (true) { + + size_t size = (size_t)rand() % max_size; + + payload = realloc(payload, size); + + printf("Spamming random payload of %zu bytes...\n", + size); + + gnutls_record_send(captured_session, payload, size); + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + + }).detach(); +} + + +void +post_gnutls_init_hook(const gnutls_session_t session) +{ + if (nullptr == captured_session) { + captured_session = session; + cv.notify_one(); + } +} diff --git a/test/fuzzing/examples/fuzz-sdp-bad-body.cpp b/test/fuzzing/examples/fuzz-sdp-bad-body.cpp new file mode 100644 index 0000000000000000000000000000000000000000..926758963a39245661099345d865f3fec305bc46 --- /dev/null +++ b/test/fuzzing/examples/fuzz-sdp-bad-body.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> + +#include "lib/gnutls.h" +#include "lib/sip-fmt.h" + +/* + * Example that will try to overflow the SDP parser. + */ +bool +mutate_gnutls_record_send(ChanneledMessage& msg) +{ + SIPFmt sip(msg.data); + + /* Only SIP request */ + if (not sip.isRequest()) { + return false; + } + + /* Skip none SDP Content-Type */ + if (not sip.isApplication("sdp")) { + return false; + } + + char payload[] = "@"; + + sip.pushBody(payload, 1); + + /* Commit changes! */ + sip.swap(msg.data); + + return true; +} diff --git a/test/fuzzing/examples/fuzz-sdp-huge-body.cpp b/test/fuzzing/examples/fuzz-sdp-huge-body.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d3e8f8ac90eea3298b81ee5b6333d21aba09795 --- /dev/null +++ b/test/fuzzing/examples/fuzz-sdp-huge-body.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> + +#include "lib/gnutls.h" +#include "lib/sip-fmt.h" + +/* + * Example that will try to overflow the SDP parser. + */ +bool +mutate_gnutls_record_send(ChanneledMessage& msg) +{ + static size_t body_repeat = 1; + + SIPFmt sip(msg.data); + + /* Only SIP request */ + if (not sip.isRequest()) { + return false; + } + + /* Skip none SDP Content-Type */ + if (not sip.isApplication("media_control+xml")) { + return false; + } + + auto body = sip.getBody(); + std::vector<uint8_t> newBody; + + newBody.reserve(body_repeat * body.size()); + + for (size_t i=0; i<body_repeat; ++i) { + for (auto it=body.cbegin(); it!=body.cend(); ++it) { + newBody.emplace_back(*it); + } + } + + sip.swapBody(newBody); + + body_repeat *= 2; + + /* Commit changes! */ + sip.swap(msg.data); + + return true; +} diff --git a/test/fuzzing/examples/fuzz-sip-html.cpp b/test/fuzzing/examples/fuzz-sip-html.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63702768d3b27bedfb7b65e62af74994aab5ff3b --- /dev/null +++ b/test/fuzzing/examples/fuzz-sip-html.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> + +#include "lib/gnutls.h" +#include "lib/sip-fmt.h" + +/* + * Insert a HTML payload in a SIP request if no content-type + */ +bool +mutate_gnutls_record_send(ChanneledMessage& msg) +{ + SIPFmt sip(msg.data); + + if (not sip.isRequest()) { + return false; + } + + if (not sip.getField("content-type").empty()) { + return false; + } + + char htmlBody[] = "<html><h1>FUZZ</h1></html>\n"; + std::vector<uint8_t> body; + + body.reserve(array_size(htmlBody)); + + for (size_t i=0; i<array_size(htmlBody); ++i) { + body.emplace_back(htmlBody[i]); + } + + sip.swapBody(body); + sip.setFieldValue("content-type", "text/html"); + + /* Commit changes! */ + sip.swap(msg.data); + + return true; +} diff --git a/test/fuzzing/examples/fuzz-sip-huge-message.cpp b/test/fuzzing/examples/fuzz-sip-huge-message.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26dace6e6c1bb63ced906ccc3b4f3edc8cf3ccff --- /dev/null +++ b/test/fuzzing/examples/fuzz-sip-huge-message.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> + +#include "lib/gnutls.h" +#include "lib/sip-fmt.h" + +/* + * Example that will try to overflow the SDP parser. + */ +bool +mutate_gnutls_record_send(ChanneledMessage& msg) +{ + static size_t body_repeat = 1; + + SIPFmt sip(msg.data); + + /* Only SIP request */ + if (not sip.isRequest()) { + return false; + } + + /* Skip none SDP Content-Type */ + if (std::string::npos == sip.getField("content-type").find("text/plain")) { + return false; + } + + auto body = sip.getBody(); + std::vector<uint8_t> newBody; + + newBody.reserve(body_repeat * body.size()); + + for (size_t i=0; i<body_repeat; ++i) { + for (auto it=body.cbegin(); it!=body.cend(); ++it) { + newBody.emplace_back(*it); + } + } + + sip.swapBody(newBody); + + body_repeat *= 2; + + /* Commit changes! */ + sip.swap(msg.data); + + return true; +} diff --git a/test/fuzzing/examples/fuzz-sip-version.cpp b/test/fuzzing/examples/fuzz-sip-version.cpp new file mode 100644 index 0000000000000000000000000000000000000000..528e58149e22475dfa4e7708a98e137b4ca088ee --- /dev/null +++ b/test/fuzzing/examples/fuzz-sip-version.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Olivier Dion <olivier.dion>@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cstdlib> + +#include "lib/gnutls.h" +#include "lib/sip-fmt.h" + +/* + * Example fuzzing wrapper that will change the SIP version sent randomly + * between 1.0 and 2.0 + */ +bool +mutate_gnutls_record_send(ChanneledMessage& msg) +{ + static int version_cnt = 0; + + SIPFmt sip(msg.data); + + if (not sip.isValid()) { + return false; + } + + char version[] = "SIP/2.0"; + char version_fmt[] = "SIP/%d.0"; + + snprintf(version, array_size(version), + version_fmt, (version_cnt++ % 2) + 1); + + sip.setVersion(version); + + /* Commit changes! */ + sip.swap(msg.data); + + return true; +}