mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-13 21:52:30 +00:00
Fix crash on untrusted XMLRPC connections
Root cause: network.rpc.use_xmlrpc and network.rpc.use_jsonrpc were not marked as untrusted-safe, but RpcManager::process() calls them before dispatching to the protocol handler. When an untrusted request arrived, call_command() threw untrusted_error for these gatekeepers, which escaped the callback_interrupt_pollling callback and crashed rtorrent. Fix: Mark network.rpc.use_xmlrpc/jsonrpc as safe (CMD2_VAR_BOOL_U). Also harden exception safety: - SCGI callback catch-all now sends a generic error response instead of re-throwing, since the callback infrastructure may not support exception propagation. - xmlrpc_c.cc now has catch(std::exception&) and catch(...) safety nets after the specific exception handlers.
This commit is contained in:
@@ -248,8 +248,8 @@ initialize_command_network() {
|
||||
CMD2_ANY_U ("network.xmlrpc.size_limit", [](const auto&, const auto&) { return rpc::rpc.size_limit(); });
|
||||
CMD2_ANY_VALUE_V_U ("network.xmlrpc.size_limit.set", [](const auto&, const auto& arg) { return rpc::rpc.set_size_limit(arg); });
|
||||
|
||||
CMD2_VAR_BOOL ("network.rpc.use_xmlrpc", true);
|
||||
CMD2_VAR_BOOL ("network.rpc.use_jsonrpc", true);
|
||||
CMD2_VAR_BOOL_U ("network.rpc.use_xmlrpc", true);
|
||||
CMD2_VAR_BOOL_U ("network.rpc.use_jsonrpc", true);
|
||||
|
||||
CMD2_ANY ("network.block.ipv4", [nw_config](auto, auto) { return nw_config->is_block_ipv4(); });
|
||||
CMD2_ANY_VALUE_V ("network.block.ipv4.set", [nw_config](auto, auto& value) { return nw_config->set_block_ipv4(value); });
|
||||
|
||||
+12
-1
@@ -3,6 +3,7 @@
|
||||
#include "rpc/scgi_task.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
@@ -315,7 +316,17 @@ SCgiTask::receive_call(const char* buffer, uint32_t length) {
|
||||
});
|
||||
} catch (...) {
|
||||
rpc::RpcManager::set_trusted(true);
|
||||
throw;
|
||||
|
||||
// Send a generic error response instead of re-throwing, as the
|
||||
// callback infrastructure may not support exception propagation.
|
||||
const char* err_xml = "<?xml version=\"1.0\"?><methodResponse><fault><value><struct>"
|
||||
"<member><name>faultCode</name><value><i8>-500</i8></value></member>"
|
||||
"<member><name>faultString</name><value><string>Internal error</string></value></member>"
|
||||
"</struct></value></fault></methodResponse>";
|
||||
const char* err_json = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Internal error\"},\"id\":null}";
|
||||
const char* err = (rpc_type == RpcManager::RPCType::JSON) ? err_json : err_xml;
|
||||
result_callback(err, std::strlen(err));
|
||||
return;
|
||||
}
|
||||
|
||||
rpc::RpcManager::set_trusted(true);
|
||||
|
||||
@@ -396,6 +396,14 @@ xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
|
||||
} catch (torrent::local_error& e) {
|
||||
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, e.what());
|
||||
return NULL;
|
||||
|
||||
} catch (std::exception& e) {
|
||||
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, e.what());
|
||||
return NULL;
|
||||
|
||||
} catch (...) {
|
||||
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, "Unknown exception in command execution.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user