From fdf2dc43d55d1ed4287dd06b4381e954b1dff558 Mon Sep 17 00:00:00 2001 From: Noah Hilverling Date: Thu, 1 Mar 2018 09:47:29 +0100 Subject: [PATCH] Limit JSON-RPC message size --- lib/base/netstring.cpp | 10 +++++++++- lib/base/netstring.hpp | 5 +++-- lib/remote/jsonrpc.cpp | 4 ++-- lib/remote/jsonrpc.hpp | 4 ++-- lib/remote/jsonrpcconnection.cpp | 7 ++++++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/base/netstring.cpp b/lib/base/netstring.cpp index 934097e2b..e77a41285 100644 --- a/lib/base/netstring.cpp +++ b/lib/base/netstring.cpp @@ -32,7 +32,8 @@ using namespace icinga; * @exception invalid_argument The input stream is invalid. * @see https://github.com/PeterScott/netstring-c/blob/master/netstring.c */ -StreamReadStatus NetString::ReadStringFromStream(const Stream::Ptr& stream, String *str, StreamReadContext& context, bool may_wait) +StreamReadStatus NetString::ReadStringFromStream(const Stream::Ptr& stream, String *str, StreamReadContext& context, + bool may_wait, ssize_t maxMessageLength) { if (context.Eof) return StatusEof; @@ -84,6 +85,13 @@ StreamReadStatus NetString::ReadStringFromStream(const Stream::Ptr& stream, Stri /* read the whole message */ size_t data_length = len + 1; + if (maxMessageLength >= 0 && data_length > maxMessageLength) { + std::stringstream errorMessage; + errorMessage << "Max data length exceeded: " << (maxMessageLength / 1024 / 1024) << " MB"; + + BOOST_THROW_EXCEPTION(std::invalid_argument(errorMessage.str())); + } + char *data = context.Buffer + header_length + 1; if (context.Size < header_length + 1 + data_length) { diff --git a/lib/base/netstring.hpp b/lib/base/netstring.hpp index c24cba028..045ef5b0b 100644 --- a/lib/base/netstring.hpp +++ b/lib/base/netstring.hpp @@ -38,8 +38,9 @@ class String; class I2_BASE_API NetString { public: - static StreamReadStatus ReadStringFromStream(const Stream::Ptr& stream, String *message, StreamReadContext& context, bool may_wait = false); - static void WriteStringToStream(const Stream::Ptr& stream, const String& message); + static StreamReadStatus ReadStringFromStream(const Stream::Ptr& stream, String *message, StreamReadContext& context, + bool may_wait = false, ssize_t maxMessageLength = -1); + static size_t WriteStringToStream(const Stream::Ptr& stream, const String& message); static void WriteStringToStream(std::ostream& stream, const String& message); private: diff --git a/lib/remote/jsonrpc.cpp b/lib/remote/jsonrpc.cpp index 1d3efd5ca..f0cca71f6 100644 --- a/lib/remote/jsonrpc.cpp +++ b/lib/remote/jsonrpc.cpp @@ -70,10 +70,10 @@ void JsonRpc::SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& mess NetString::WriteStringToStream(stream, json); } -StreamReadStatus JsonRpc::ReadMessage(const Stream::Ptr& stream, String *message, StreamReadContext& src, bool may_wait) +StreamReadStatus JsonRpc::ReadMessage(const Stream::Ptr& stream, String *message, StreamReadContext& src, bool may_wait, ssize_t maxMessageLength) { String jsonString; - StreamReadStatus srs = NetString::ReadStringFromStream(stream, &jsonString, src, may_wait); + StreamReadStatus srs = NetString::ReadStringFromStream(stream, &jsonString, src, may_wait, maxMessageLength); if (srs != StatusNewItem) return srs; diff --git a/lib/remote/jsonrpc.hpp b/lib/remote/jsonrpc.hpp index 3589b365a..6ab83e35f 100644 --- a/lib/remote/jsonrpc.hpp +++ b/lib/remote/jsonrpc.hpp @@ -35,8 +35,8 @@ namespace icinga class I2_REMOTE_API JsonRpc { public: - static void SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& message); - static StreamReadStatus ReadMessage(const Stream::Ptr& stream, String *message, StreamReadContext& src, bool may_wait = false); + static size_t SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& message); + static StreamReadStatus ReadMessage(const Stream::Ptr& stream, String *message, StreamReadContext& src, bool may_wait = false, ssize_t maxMessageLength = -1); static Dictionary::Ptr DecodeMessage(const String& message); private: diff --git a/lib/remote/jsonrpcconnection.cpp b/lib/remote/jsonrpcconnection.cpp index 161a9d015..ac23a1060 100644 --- a/lib/remote/jsonrpcconnection.cpp +++ b/lib/remote/jsonrpcconnection.cpp @@ -237,9 +237,14 @@ void JsonRpcConnection::MessageHandler(const String& jsonString) bool JsonRpcConnection::ProcessMessage(void) { + ssize_t maxMessageLength = 64 * 1024; + + if (m_Endpoint) + maxMessageLength = -1; /* no limit */ + String message; - StreamReadStatus srs = JsonRpc::ReadMessage(m_Stream, &message, m_Context, false); + StreamReadStatus srs = JsonRpc::ReadMessage(m_Stream, &message, m_Context, false, maxMessageLength); if (srs != StatusNewItem) return false; -- 2.40.0