summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-05-04 14:14:19 +0100
committerSadie Powell <sadie@witchery.services>2025-05-04 14:14:19 +0100
commit4b854d39357cbcfa43eb833949d48a49b0420ad6 (patch)
treebdc625b02f2366a64c68ed33826250894e1fa9c0 /modules
parent0b2b00b37dd2e713129a04bdae4c5b8aab858126 (diff)
Add support for bearer tokens for authorising with RPC.
Diffstat (limited to 'modules')
-rw-r--r--modules/extra/xmlrpc.cpp26
-rw-r--r--modules/rpc/jsonrpc.cpp28
2 files changed, 51 insertions, 3 deletions
diff --git a/modules/extra/xmlrpc.cpp b/modules/extra/xmlrpc.cpp
index de23f0dc1..24f5f5f0e 100644
--- a/modules/extra/xmlrpc.cpp
+++ b/modules/extra/xmlrpc.cpp
@@ -93,6 +93,17 @@ public:
request.name = method;
delete method;
+ if (!tokens.empty())
+ {
+ auto it = message.headers.find("Authorization");
+ if (it == message.headers.end() || !CanExecute(it->second, request.name))
+ {
+ xmlrpc_env_set_fault(&env, RPC::ERR_METHOD_NOT_FOUND, "No authorization for method");
+ SendError(reply, env);
+ return true;
+ }
+ }
+
ServiceReference<RPC::Event> event(RPC_EVENT, request.name);
if (!event)
{
@@ -308,8 +319,21 @@ public:
this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", modconf.Get<const Anope::string>("server", "httpd/main"));
if (!httpref)
throw ConfigException("Unable to find http reference, is httpd loaded?");
- httpref->RegisterPage(&xmlrpcinterface);
+ xmlrpcinterface.tokens.clear();
+ for (int i = 0; i < modconf.CountBlock("token"); ++i)
+ {
+ const auto &block = modconf.GetBlock("token", i);
+ const auto &token = block.Get<const Anope::string>("token");
+ if (!token.empty())
+ {
+ std::vector<Anope::string> methods;
+ spacesepstream(block.Get<const Anope::string>("methods")).GetTokens(methods);
+ xmlrpcinterface.tokens.emplace(token, methods);
+ }
+ }
+
+ httpref->RegisterPage(&xmlrpcinterface);
}
};
diff --git a/modules/rpc/jsonrpc.cpp b/modules/rpc/jsonrpc.cpp
index cb6835d47..8069ed8eb 100644
--- a/modules/rpc/jsonrpc.cpp
+++ b/modules/rpc/jsonrpc.cpp
@@ -99,7 +99,7 @@ public:
auto *doc = yyjson_read_opts(const_cast<char *>(message.content.c_str()), message.content.length(), flags, nullptr, &error);
if (!doc)
{
- SendError(reply, RPC::ERR_PARSE_ERROR, Anope::printf("JSON parse error #%u: %s", error.code, error.msg));
+ SendError(reply, RPC::ERR_PARSE_ERROR, Anope::printf("JSON parse error #%u: %s", error.code, error.msg));
return true;
}
@@ -131,6 +131,16 @@ public:
return true;
}
+ if (!tokens.empty())
+ {
+ auto it = message.headers.find("Authorization");
+ if (it == message.headers.end() || !CanExecute(it->second, request.name))
+ {
+ SendError(reply, RPC::ERR_METHOD_NOT_FOUND, "No authorization for method: " + request.name, id);
+ return true;
+ }
+ }
+
auto *params = yyjson_obj_get(root, "params");
size_t idx, max;
yyjson_val *val;
@@ -262,10 +272,24 @@ public:
if (httpref)
httpref->UnregisterPage(&jsonrpcinterface);
- this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", conf.GetModule(this).Get<const Anope::string>("server", "httpd/main"));
+ const auto &modconf = conf.GetModule(this);
+ this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", modconf.Get<const Anope::string>("server", "httpd/main"));
if (!httpref)
throw ConfigException("Unable to find http reference, is httpd loaded?");
+ jsonrpcinterface.tokens.clear();
+ for (int i = 0; i < modconf.CountBlock("token"); ++i)
+ {
+ const auto &block = modconf.GetBlock("token", i);
+ const auto &token = block.Get<const Anope::string>("token");
+ if (!token.empty())
+ {
+ std::vector<Anope::string> methods;
+ spacesepstream(block.Get<const Anope::string>("methods")).GetTokens(methods);
+ jsonrpcinterface.tokens.emplace(token, methods);
+ }
+ }
+
httpref->RegisterPage(&jsonrpcinterface);
}
};