mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-24 22:24:44 +02:00
Merge pull request #6135 from Icinga/fix/limit-api-package-size
Limit JSON RPC message size
This commit is contained in:
commit
9b72a6c2f3
@ -32,7 +32,8 @@ using namespace icinga;
|
|||||||
* @exception invalid_argument The input stream is invalid.
|
* @exception invalid_argument The input stream is invalid.
|
||||||
* @see https://github.com/PeterScott/netstring-c/blob/master/netstring.c
|
* @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)
|
if (context.Eof)
|
||||||
return StatusEof;
|
return StatusEof;
|
||||||
@ -84,6 +85,13 @@ StreamReadStatus NetString::ReadStringFromStream(const Stream::Ptr& stream, Stri
|
|||||||
/* read the whole message */
|
/* read the whole message */
|
||||||
size_t data_length = len + 1;
|
size_t data_length = len + 1;
|
||||||
|
|
||||||
|
if (maxMessageLength >= 0 && data_length > maxMessageLength) {
|
||||||
|
std::stringstream errorMessage;
|
||||||
|
errorMessage << "Max data length exceeded: " << (maxMessageLength / 1024) << " KB";
|
||||||
|
|
||||||
|
BOOST_THROW_EXCEPTION(std::invalid_argument(errorMessage.str()));
|
||||||
|
}
|
||||||
|
|
||||||
char *data = context.Buffer + header_length + 1;
|
char *data = context.Buffer + header_length + 1;
|
||||||
|
|
||||||
if (context.Size < header_length + 1 + data_length) {
|
if (context.Size < header_length + 1 + data_length) {
|
||||||
|
@ -38,7 +38,8 @@ class String;
|
|||||||
class NetString
|
class NetString
|
||||||
{
|
{
|
||||||
public:
|
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 size_t WriteStringToStream(const Stream::Ptr& stream, const String& message);
|
||||||
static void WriteStringToStream(std::ostream& stream, const String& message);
|
static void WriteStringToStream(std::ostream& stream, const String& message);
|
||||||
|
|
||||||
|
@ -547,8 +547,12 @@ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const Stri
|
|||||||
endpoint->AddClient(aclient);
|
endpoint->AddClient(aclient);
|
||||||
|
|
||||||
m_SyncQueue.Enqueue(std::bind(&ApiListener::SyncClient, this, aclient, endpoint, needSync));
|
m_SyncQueue.Enqueue(std::bind(&ApiListener::SyncClient, this, aclient, endpoint, needSync));
|
||||||
} else
|
} else {
|
||||||
AddAnonymousClient(aclient);
|
if (!AddAnonymousClient(aclient)) {
|
||||||
|
Log(LogNotice, "ApiListener", "Ignoring anonymous JSON-RPC connection. Max connections exceeded.");
|
||||||
|
aclient->Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log(LogNotice, "ApiListener", "New HTTP client");
|
Log(LogNotice, "ApiListener", "New HTTP client");
|
||||||
|
|
||||||
@ -1360,10 +1364,14 @@ double ApiListener::CalculateZoneLag(const Endpoint::Ptr& endpoint)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiListener::AddAnonymousClient(const JsonRpcConnection::Ptr& aclient)
|
bool ApiListener::AddAnonymousClient(const JsonRpcConnection::Ptr& aclient)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_AnonymousClientsLock);
|
boost::mutex::scoped_lock lock(m_AnonymousClientsLock);
|
||||||
|
if (m_AnonymousClients.size() > 25)
|
||||||
|
return false;
|
||||||
|
|
||||||
m_AnonymousClients.insert(aclient);
|
m_AnonymousClients.insert(aclient);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiListener::RemoveAnonymousClient(const JsonRpcConnection::Ptr& aclient)
|
void ApiListener::RemoveAnonymousClient(const JsonRpcConnection::Ptr& aclient)
|
||||||
|
@ -79,7 +79,7 @@ public:
|
|||||||
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
|
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
|
||||||
std::pair<Dictionary::Ptr, Dictionary::Ptr> GetStatus();
|
std::pair<Dictionary::Ptr, Dictionary::Ptr> GetStatus();
|
||||||
|
|
||||||
void AddAnonymousClient(const JsonRpcConnection::Ptr& aclient);
|
bool AddAnonymousClient(const JsonRpcConnection::Ptr& aclient);
|
||||||
void RemoveAnonymousClient(const JsonRpcConnection::Ptr& aclient);
|
void RemoveAnonymousClient(const JsonRpcConnection::Ptr& aclient);
|
||||||
std::set<JsonRpcConnection::Ptr> GetAnonymousClients() const;
|
std::set<JsonRpcConnection::Ptr> GetAnonymousClients() const;
|
||||||
|
|
||||||
|
@ -72,10 +72,10 @@ size_t JsonRpc::SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& me
|
|||||||
return NetString::WriteStringToStream(stream, json);
|
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;
|
String jsonString;
|
||||||
StreamReadStatus srs = NetString::ReadStringFromStream(stream, &jsonString, src, may_wait);
|
StreamReadStatus srs = NetString::ReadStringFromStream(stream, &jsonString, src, may_wait, maxMessageLength);
|
||||||
|
|
||||||
if (srs != StatusNewItem)
|
if (srs != StatusNewItem)
|
||||||
return srs;
|
return srs;
|
||||||
|
@ -36,7 +36,7 @@ class JsonRpc
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static size_t SendMessage(const Stream::Ptr& stream, const Dictionary::Ptr& message);
|
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);
|
static Dictionary::Ptr DecodeMessage(const String& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -250,9 +250,14 @@ void JsonRpcConnection::MessageHandler(const String& jsonString)
|
|||||||
|
|
||||||
bool JsonRpcConnection::ProcessMessage()
|
bool JsonRpcConnection::ProcessMessage()
|
||||||
{
|
{
|
||||||
|
ssize_t maxMessageLength = 64 * 1024;
|
||||||
|
|
||||||
|
if (m_Endpoint)
|
||||||
|
maxMessageLength = -1; /* no limit */
|
||||||
|
|
||||||
String message;
|
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)
|
if (srs != StatusNewItem)
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user