Skip to content

Commit c575a58

Browse files
committed
feat: change handler to '/' for external users, use only rpc user name to choose queue
1 parent f1c1fd8 commit c575a58

File tree

5 files changed

+37
-38
lines changed

5 files changed

+37
-38
lines changed

src/httprpc.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,6 @@ static bool HTTPReq_JSONRPC(const CoreContext& context, HTTPRequest* req, bool e
176176
return false;
177177
}
178178

179-
if (jreq.authUser == gArgs.GetArg("-rpcexternaluser", "") && !jreq.authUser.empty()) {
180-
if (!external) {
181-
LogPrintf("RPC User '%s' is allowed to call rpc only by path /external\n", jreq.authUser);
182-
req->WriteReply(HTTP_FORBIDDEN);
183-
return false;
184-
}
185-
LogPrintf("RPC user '%s' is external\n", jreq.authUser);
186-
}
187179
try {
188180
// Parse request
189181
UniValue valRequest;
@@ -306,12 +298,10 @@ bool StartHTTPRPC(const CoreContext& context)
306298
return false;
307299

308300
auto handle_rpc = [&context](HTTPRequest* req, const std::string&) { return HTTPReq_JSONRPC(context, req); };
309-
auto handle_rpc_external = [&context](HTTPRequest* req, const std::string&) { return HTTPReq_JSONRPC(context, req, true); };
310-
RegisterHTTPHandler("/", true, false, handle_rpc);
301+
RegisterHTTPHandler("/", true, handle_rpc);
311302
if (g_wallet_init_interface.HasWalletSupport()) {
312-
RegisterHTTPHandler("/wallet/", false, false, handle_rpc);
303+
RegisterHTTPHandler("/wallet/", false, handle_rpc);
313304
}
314-
RegisterHTTPHandler("/external", true, true, handle_rpc_external);
315305
struct event_base* eventBase = EventBase();
316306
assert(eventBase);
317307
httpRPCTimerInterface = std::make_unique<HTTPRPCTimerInterface>(eventBase);
@@ -327,7 +317,6 @@ void InterruptHTTPRPC()
327317
void StopHTTPRPC()
328318
{
329319
LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n");
330-
UnregisterHTTPHandler("/external", true);
331320
UnregisterHTTPHandler("/", true);
332321
if (g_wallet_init_interface.HasWalletSupport()) {
333322
UnregisterHTTPHandler("/wallet/", false);

src/httpserver.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,12 @@ class WorkQueue
126126

127127
struct HTTPPathHandler
128128
{
129-
HTTPPathHandler(std::string _prefix, bool _exactMatch, bool external, HTTPRequestHandler _handler):
130-
prefix(_prefix), exactMatch(_exactMatch), m_external(external), handler(_handler)
129+
HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler):
130+
prefix(_prefix), exactMatch(_exactMatch), handler(_handler)
131131
{
132132
}
133133
std::string prefix;
134134
bool exactMatch;
135-
bool m_external;
136135
HTTPRequestHandler handler;
137136
};
138137

@@ -262,14 +261,31 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
262261
break;
263262
}
264263
}
264+
const bool is_external_request = [&hreq]() -> bool {
265+
const std::string external_username = gArgs.GetArg("-rpcexternaluser", "");
266+
if (external_username.empty()) return false;
267+
268+
const std::string strAuth = hreq->GetHeader("authorization").second;
269+
if (strAuth.substr(0, 6) != "Basic ")
270+
return false;
271+
272+
std::string strUserPass64 = TrimString(strAuth.substr(6));
273+
bool invalid;
274+
std::string strUserPass = DecodeBase64(strUserPass64, &invalid);
275+
if (invalid) return false;
276+
277+
if (strUserPass.find(':') == std::string::npos) return false;
278+
279+
return strUserPass.substr(0, strUserPass.find(':')) == external_username;
280+
}();
265281

266282
// Dispatch to worker thread
267283
if (i != iend) {
268-
auto item{std::make_unique<HTTPWorkItem>(std::move(hreq), path, i->handler)}; /// this handler!
284+
auto item{std::make_unique<HTTPWorkItem>(std::move(hreq), path, i->handler)};
269285
assert(g_work_queue);
270286

271287
// We have queue created only if RPC arg 'rpcexternaluser' is specified
272-
if (i->m_external && g_work_queue_external) {
288+
if (is_external_request && g_work_queue_external) {
273289
if (g_work_queue_external->Enqueue(item.get())) {
274290
item.release();
275291
} else {
@@ -673,10 +689,10 @@ HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() const
673689
}
674690
}
675691

676-
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, bool external, const HTTPRequestHandler &handler)
692+
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
677693
{
678-
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d external %d)\n", prefix, exactMatch, external);
679-
pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, external, handler));
694+
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
695+
pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler));
680696
}
681697

682698
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)

src/httpserver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ typedef std::function<bool(HTTPRequest* req, const std::string &)> HTTPRequestHa
4141
* If multiple handlers match a prefix, the first-registered one will
4242
* be invoked.
4343
*/
44-
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, bool external, const HTTPRequestHandler &handler);
44+
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler);
4545
/** Unregister handler for prefix */
4646
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch);
4747

src/rest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ void StartREST(const CoreContext& context)
723723
{
724724
for (const auto& up : uri_prefixes) {
725725
auto handler = [&context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); };
726-
RegisterHTTPHandler(up.prefix, false, false, handler);
726+
RegisterHTTPHandler(up.prefix, false, handler);
727727
}
728728
}
729729

test/functional/rpc_platform_filter.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,12 @@ def run_test(self):
4343
url = urllib.parse.urlparse(self.nodes[0].url)
4444

4545
def test_command(method, params, auth, expected_status, should_not_match=False):
46-
test_command_helper(method, params, '/', auth, expected_status, should_not_match)
47-
48-
def test_external_command(method, params, auth, expected_status, should_not_match=False):
49-
test_command_helper(method, params, '/external', auth, expected_status, should_not_match)
50-
51-
def test_command_helper(method, params, path, auth, expected_status, should_not_match):
5246
conn = http.client.HTTPConnection(url.hostname, url.port)
5347
conn.connect()
5448
body = {"method": method}
5549
if len(params):
5650
body["params"] = params
57-
conn.request('POST', path, json.dumps(body), {"Authorization": "Basic " + str_to_b64str(auth)})
51+
conn.request('POST', '/', json.dumps(body), {"Authorization": "Basic " + str_to_b64str(auth)})
5852
resp = conn.getresponse()
5953
if should_not_match:
6054
assert resp.status != expected_status
@@ -120,15 +114,15 @@ def test_command_helper(method, params, path, auth, expected_status, should_not_
120114
test_command("debug", ["1"], rpcuser_authpair_operator, 200)
121115

122116

123-
self.log.info("Restart node with /external handler...")
124-
test_external_command("getbestblockhash", [], rpcuser_authpair_platform, 200)
125-
test_external_command("getblockchaininfo", [], rpcuser_authpair_platform, 403)
126-
117+
self.log.info("Restart node with -rpcexternaluser...")
127118
self.restart_node(0, extra_args=["-rpcexternaluser=platform-user"])
128-
test_command("getbestblockhash", [], rpcuser_authpair_platform, 403)
129-
test_external_command("getbestblockhash", [], rpcuser_authpair_platform, 200)
130-
test_external_command("getblockchaininfo", [], rpcuser_authpair_platform, 403)
131-
test_external_command("getbestblockhash", [], rpcuser_authpair_operator, 200)
119+
120+
external_log_str = "HTTP: Calling handler for external user"
121+
expected_log_str = "ThreadRPCServer method="
122+
with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_str, external_log_str]):
123+
test_command("getbestblockhash", [], rpcuser_authpair_platform, 200)
124+
with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_str], unexpected_msgs = [external_log_str]):
125+
test_command("getbestblockhash", [], rpcuser_authpair_operator, 200)
132126

133127

134128

0 commit comments

Comments
 (0)