diff options
author | Sadie Powell <sadie@witchery.services> | 2025-05-04 14:14:19 +0100 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2025-05-04 14:14:19 +0100 |
commit | 4b854d39357cbcfa43eb833949d48a49b0420ad6 (patch) | |
tree | bdc625b02f2366a64c68ed33826250894e1fa9c0 /modules | |
parent | 0b2b00b37dd2e713129a04bdae4c5b8aab858126 (diff) |
Add support for bearer tokens for authorising with RPC.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/extra/xmlrpc.cpp | 26 | ||||
-rw-r--r-- | modules/rpc/jsonrpc.cpp | 28 |
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); } }; |