]> granicus.if.org Git - icinga2/commitdiff
Limit JSON-RPC message size
authorNoah Hilverling <noah.hilverling@icinga.com>
Thu, 1 Mar 2018 08:47:29 +0000 (09:47 +0100)
committerGunnar Beutner <gunnar.beutner@icinga.com>
Mon, 5 Mar 2018 09:29:05 +0000 (10:29 +0100)
lib/base/netstring.cpp
lib/base/netstring.hpp
lib/remote/jsonrpc.cpp
lib/remote/jsonrpc.hpp
lib/remote/jsonrpcconnection.cpp

index 0bd110bacffd30a0fc22bea125d2025fa8fc72b5..e970f3b61d4c9f6491bc24235054b59f7b94ffd9 100644 (file)
@@ -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) {
index 4ba02ccd34b8de7c714cdefc10cf59e456a94dae..1daaa979acb23a6186cd827ff504f67802d69f7e 100644 (file)
@@ -38,7 +38,8 @@ class String;
 class NetString
 {
 public:
-       static StreamReadStatus ReadStringFromStream(const Stream::Ptr& stream, String *message, StreamReadContext& context, bool may_wait = false);
+       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);
 
index 94bd9cb5be880557df9e410a8cb5c703712aa2a2..3dbd13aa3d8db153bc793b6b28c14dd71f6ef8ea 100644 (file)
@@ -72,10 +72,10 @@ size_t JsonRpc::SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& me
        return 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, size_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;
index 1d3232f955060dc2e38fdd92573e4db6fa2ee000..3b0eaabf803b8ea3409c6d58002b3a7e914fa18d 100644 (file)
@@ -36,7 +36,7 @@ class JsonRpc
 {
 public:
        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);
+       static StreamReadStatus ReadMessage(const Stream::Ptr& stream, String *message, StreamReadContext& src, bool may_wait = false, size_t maxMessageLength = -1);
        static Dictionary::Ptr DecodeMessage(const String& message);
 
 private:
index 978cd9658d3544f7871ee9c018ddf33c9f261c0b..bbb6fe1803b6f82084b5262e8eeef6c094a1bbc6 100644 (file)
@@ -250,9 +250,14 @@ void JsonRpcConnection::MessageHandler(const String& jsonString)
 
 bool JsonRpcConnection::ProcessMessage()
 {
+       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;