Add size limit to XML-RPC documents, defaulting to max SCGI size

This commit is contained in:
kannibalox
2024-11-02 13:15:52 -04:00
committed by Jari Sundell
parent cadfcb50d2
commit d6dcbc4a69
4 changed files with 33 additions and 9 deletions
+11 -5
View File
@@ -37,6 +37,8 @@
#ifndef RTORRENT_RPC_XMLRPC_H
#define RTORRENT_RPC_XMLRPC_H
#include "scgi_task.h"
#include <functional>
#include <torrent/hash_string.h>
@@ -74,7 +76,7 @@ public:
static const int call_file = 5;
static const int call_file_itr = 6;
XmlRpc() : m_env(NULL), m_registry(NULL), m_dialect(dialect_i8) {}
XmlRpc() : m_env(NULL), m_registry(NULL), m_dialect(dialect_i8), m_sizeLimit(SCgiTask::max_content_size) {}
bool is_valid() const;
@@ -97,17 +99,21 @@ public:
void set_size_limit(uint64_t size);
private:
slot_download m_slotFindDownload;
slot_file m_slotFindFile;
slot_tracker m_slotFindTracker;
slot_peer m_slotFindPeer;
// Only used by xmlrpc-c
void* m_env;
void* m_registry;
int m_dialect;
// Only used by tinyxml2
bool m_isValid;
uint64_t m_sizeLimit;
slot_download m_slotFindDownload;
slot_file m_slotFindFile;
slot_tracker m_slotFindTracker;
slot_peer m_slotFindPeer;
};
}
+7 -2
View File
@@ -423,6 +423,11 @@ print_xmlrpc_fault(int faultCode, std::string faultString, tinyxml2::XMLPrinter*
bool
XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) {
if (length > m_sizeLimit) {
tinyxml2::XMLPrinter printer(nullptr, true, 0);
print_xmlrpc_fault(XMLRPC_LIMIT_EXCEEDED_ERROR, "Content size exceeds maximum XML-RPC limit", &printer);
return slotWrite(printer.CStr(), printer.CStrSize()-1);
}
tinyxml2::XMLDocument doc;
doc.Parse(inBuffer, length);
try {
@@ -449,8 +454,8 @@ void XmlRpc::cleanup() {}
void XmlRpc::insert_command(const char*, const char*, const char*) {}
void XmlRpc::set_dialect(int) {}
int64_t XmlRpc::size_limit() { return std::numeric_limits<int64_t>::max(); }
void XmlRpc::set_size_limit(uint64_t) {}
int64_t XmlRpc::size_limit() { return m_sizeLimit; }
void XmlRpc::set_size_limit(uint64_t limit) { m_sizeLimit = limit; }
bool XmlRpc::is_valid() const { return m_isValid; }
+13 -2
View File
@@ -57,7 +57,7 @@ XmlrpcTest::test_basics() {
// Sanity check the above parser
CPPUNIT_ASSERT_MESSAGE("Could not parse test data", inputs.size() > 0 && inputs.size() == outputs.size() && inputs.size() == titles.size());
for (int i = 0; i < inputs.size(); i++) {
auto output = std::string("");
std::string output;
m_xmlrpc.process(inputs[i].c_str(), inputs[i].size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;});
CPPUNIT_ASSERT_EQUAL_MESSAGE(titles[i], std::string(outputs[i]), output);
}
@@ -70,12 +70,23 @@ XmlrpcTest::test_invalid_utf8() {
// just a series of bytes so it reflects just fine.
std::string input = "<?xml version=\"1.0\"?><methodCall><methodName>xmlrpc_reflect</methodName><params><param><value><string></string></value></param><param><value><string>\xc3\x28</string></value></param></params></methodCall>";
std::string expected = "<?xml version=\"1.0\"?><methodReponse><params><param><value><array><value><string>\xc3\x28</string></value></array></value></param></params></methodReponse>";
auto output = std::string("");
std::string output;
m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;});
CPPUNIT_ASSERT_EQUAL(expected, output);
}
void
XmlrpcTest::test_size_limit() {
std::string input = "<?xml version=\"1.0\"?><methodCall><methodName>xmlrpc_reflect</methodName><params><param><value><string></string></value></param><param><value><string>\xc3\x28</string></value></param></params></methodCall>";
std::string expected = "<?xml version=\"1.0\"?><methodReponse><fault><struct><member><name>faultCode</name><value><int>-509</int></value></member><member><name>faultString</name><value><string>Content size exceeds maximum XML-RPC limit</string></value></member></struct></fault></methodReponse>";
std::string output;
m_xmlrpc.set_size_limit(1);
m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;});
CPPUNIT_ASSERT_EQUAL(expected, output);
}
#else
void XmlrpcTest::test_invalid_utf8() {}
void XmlrpcTest::test_basics() {}
void XmlrpcTest::test_size_limit() {}
void XmlrpcTest::setUp() {}
#endif
+2
View File
@@ -7,6 +7,7 @@ class XmlrpcTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(XmlrpcTest);
CPPUNIT_TEST(test_basics);
CPPUNIT_TEST(test_invalid_utf8);
CPPUNIT_TEST(test_size_limit);
CPPUNIT_TEST_SUITE_END();
public:
@@ -17,6 +18,7 @@ public:
void test_basics();
void test_invalid_utf8();
void test_size_limit();
private:
rpc::XmlRpc m_xmlrpc;