mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-13 11:40:42 +02:00
Merge 19117 via rpc_getrpcwhitelist
This commit is contained in:
commit
fcb36072f9
@ -419,3 +419,20 @@ void StopHTTPRPC()
|
|||||||
httpRPCTimerInterface.reset();
|
httpRPCTimerInterface.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::set<std::string> GetWhitelistedRpcs(const std::string& user_name)
|
||||||
|
{
|
||||||
|
if (auto it = g_rpc_whitelist.find(user_name); it != g_rpc_whitelist.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
if (g_rpc_whitelist_default) {
|
||||||
|
return std::set<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a list of every method
|
||||||
|
std::set<std::string> allowed_methods;
|
||||||
|
for (const auto& method_name : tableRPC.listCommands()) {
|
||||||
|
allowed_methods.insert(method_name);
|
||||||
|
}
|
||||||
|
return allowed_methods;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#define BITCOIN_HTTPRPC_H
|
#define BITCOIN_HTTPRPC_H
|
||||||
|
|
||||||
#include <any>
|
#include <any>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/** Start HTTP RPC subsystem.
|
/** Start HTTP RPC subsystem.
|
||||||
* Precondition; HTTP and RPC has been started.
|
* Precondition; HTTP and RPC has been started.
|
||||||
@ -31,4 +33,8 @@ void InterruptREST();
|
|||||||
*/
|
*/
|
||||||
void StopREST();
|
void StopREST();
|
||||||
|
|
||||||
|
/** Returns a collection of whitelisted RPCs for the given user
|
||||||
|
*/
|
||||||
|
std::set<std::string> GetWhitelistedRpcs(const std::string& user_name);
|
||||||
|
|
||||||
#endif // BITCOIN_HTTPRPC_H
|
#endif // BITCOIN_HTTPRPC_H
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <common/args.h>
|
#include <common/args.h>
|
||||||
#include <common/system.h>
|
#include <common/system.h>
|
||||||
|
#include <httprpc.h>
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
#include <rpc/request.h>
|
#include <rpc/request.h>
|
||||||
@ -259,9 +260,43 @@ static RPCHelpMan getrpcinfo()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RPCHelpMan getrpcwhitelist()
|
||||||
|
{
|
||||||
|
return RPCHelpMan{"getrpcwhitelist",
|
||||||
|
"\nReturns whitelisted RPCs for the current user.\n",
|
||||||
|
{},
|
||||||
|
RPCResult{
|
||||||
|
RPCResult::Type::OBJ, "", "",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::OBJ_DYN, "methods", "List of RPCs that the user is allowed to call",
|
||||||
|
{
|
||||||
|
{RPCResult::Type::NONE, "rpc", "Key is name of RPC method, value is null"},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RPCExamples{
|
||||||
|
HelpExampleCli("getrpcwhitelist", "")
|
||||||
|
+ HelpExampleRpc("getrpcwhitelist", "")},
|
||||||
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
|
{
|
||||||
|
UniValue whitelisted_rpcs(UniValue::VOBJ);
|
||||||
|
const std::set<std::string>& whitelist = GetWhitelistedRpcs(request.authUser);
|
||||||
|
for (const auto& rpc : whitelist) {
|
||||||
|
whitelisted_rpcs.pushKV(rpc, NullUniValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.pushKV("methods", whitelisted_rpcs);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static const CRPCCommand vRPCCommands[]{
|
static const CRPCCommand vRPCCommands[]{
|
||||||
/* Overall control/query calls */
|
/* Overall control/query calls */
|
||||||
{"control", &getrpcinfo},
|
{"control", &getrpcinfo},
|
||||||
|
{"control", &getrpcwhitelist},
|
||||||
{"control", &help},
|
{"control", &help},
|
||||||
{"control", &stop},
|
{"control", &stop},
|
||||||
{"control", &uptime},
|
{"control", &uptime},
|
||||||
|
@ -157,6 +157,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
|
|||||||
"getrawmempool",
|
"getrawmempool",
|
||||||
"getrawtransaction",
|
"getrawtransaction",
|
||||||
"getrpcinfo",
|
"getrpcinfo",
|
||||||
|
"getrpcwhitelist",
|
||||||
"gettxout",
|
"gettxout",
|
||||||
"gettxoutsetinfo",
|
"gettxoutsetinfo",
|
||||||
"gettxspendingprevout",
|
"gettxspendingprevout",
|
||||||
|
74
test/functional/rpc_getrpcwhitelist.py
Executable file
74
test/functional/rpc_getrpcwhitelist.py
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2017-2020 The Bitcoin Core developers
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
"""
|
||||||
|
Test getrpcwhitelist RPC call.
|
||||||
|
"""
|
||||||
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
|
from test_framework.util import (
|
||||||
|
assert_equal,
|
||||||
|
get_datadir_path,
|
||||||
|
str_to_b64str
|
||||||
|
)
|
||||||
|
import http.client
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
def call_rpc(node, settings, rpc):
|
||||||
|
url = urllib.parse.urlparse(node.url)
|
||||||
|
headers = {"Authorization": "Basic " + str_to_b64str('{}:{}'.format(settings[0], settings[2]))}
|
||||||
|
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||||
|
conn.connect()
|
||||||
|
conn.request('POST', '/', '{"method": "' + rpc + '"}', headers)
|
||||||
|
resp = conn.getresponse()
|
||||||
|
code = resp.status
|
||||||
|
if code == 200:
|
||||||
|
json_ret = json.loads(resp.read().decode())
|
||||||
|
else:
|
||||||
|
json_ret = {"result": None}
|
||||||
|
conn.close()
|
||||||
|
return {"status": code, "json": json_ret['result']}
|
||||||
|
|
||||||
|
class RPCWhitelistTest(BitcoinTestFramework):
|
||||||
|
def set_test_params(self):
|
||||||
|
self.num_nodes = 1
|
||||||
|
|
||||||
|
def setup_chain(self):
|
||||||
|
super().setup_chain()
|
||||||
|
self.settings = ["dummy",
|
||||||
|
"4e799db4b65924f4468b1c9ff3a68109$5fcd282dcaf4ae74599934a543626c0a11e7e83ead30f07b182058ead8e85da9",
|
||||||
|
"dummypwd",
|
||||||
|
"getbalance,getrpcwhitelist,getwalletinfo"]
|
||||||
|
self.settings_forbidden = ["dummy2",
|
||||||
|
"f3d319f64b076012f75626c9d895fced$7f55381a24fda02c5de7c18fc377f56fc573149b4d6f83daa9fd584210b51f99",
|
||||||
|
"dummy2pwd",
|
||||||
|
"getbalance,getwalletinfo"]
|
||||||
|
|
||||||
|
# declare rpc-whitelisting entries
|
||||||
|
with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f:
|
||||||
|
f.write("\nrpcwhitelistdefault=0\n")
|
||||||
|
f.write("rpcauth={}:{}\n".format(self.settings[0], self.settings[1]))
|
||||||
|
f.write("rpcwhitelist={}:{}\n".format(self.settings[0], self.settings[3]))
|
||||||
|
f.write("rpcauth={}:{}\n".format(self.settings_forbidden[0], self.settings_forbidden[1]))
|
||||||
|
f.write("rpcwhitelist={}:{}\n".format(self.settings_forbidden[0], self.settings_forbidden[3]))
|
||||||
|
|
||||||
|
def run_test(self):
|
||||||
|
self.log.info("Test getrpcwhitelist")
|
||||||
|
whitelisted = {method: None for method in self.settings[3].split(',')}
|
||||||
|
|
||||||
|
# should return allowed rpcs
|
||||||
|
result = call_rpc(self.nodes[0], self.settings, 'getrpcwhitelist')
|
||||||
|
assert_equal(200, result['status'])
|
||||||
|
assert_equal(result['json']['methods'], whitelisted)
|
||||||
|
# should fail because user has no rpcwhitelist-rpc entry in bitcoin.conf
|
||||||
|
result = call_rpc(self.nodes[0], self.settings_forbidden, 'getrpcwhitelist')
|
||||||
|
assert_equal(result['status'], 403)
|
||||||
|
|
||||||
|
# should return a long list of allowed RPC methods (ie, all of them)
|
||||||
|
result = self.nodes[0].getrpcwhitelist()
|
||||||
|
assert len(result['methods']) > 10
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
RPCWhitelistTest(__file__).main()
|
@ -225,6 +225,7 @@ BASE_SCRIPTS = [
|
|||||||
'interface_usdt_validation.py',
|
'interface_usdt_validation.py',
|
||||||
'rpc_users.py',
|
'rpc_users.py',
|
||||||
'rpc_whitelist.py',
|
'rpc_whitelist.py',
|
||||||
|
'rpc_getrpcwhitelist.py',
|
||||||
'feature_proxy.py',
|
'feature_proxy.py',
|
||||||
'wallet_signrawtransactionwithwallet.py --legacy-wallet',
|
'wallet_signrawtransactionwithwallet.py --legacy-wallet',
|
||||||
'wallet_signrawtransactionwithwallet.py --descriptors',
|
'wallet_signrawtransactionwithwallet.py --descriptors',
|
||||||
|
@ -13,6 +13,7 @@ import sys
|
|||||||
|
|
||||||
EXPECTED_CIRCULAR_DEPENDENCIES = (
|
EXPECTED_CIRCULAR_DEPENDENCIES = (
|
||||||
"chainparamsbase -> common/args -> chainparamsbase",
|
"chainparamsbase -> common/args -> chainparamsbase",
|
||||||
|
"httprpc -> rpc/server -> httprpc",
|
||||||
"node/blockstorage -> validation -> node/blockstorage",
|
"node/blockstorage -> validation -> node/blockstorage",
|
||||||
"node/utxo_snapshot -> validation -> node/utxo_snapshot",
|
"node/utxo_snapshot -> validation -> node/utxo_snapshot",
|
||||||
"qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel",
|
"qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel",
|
||||||
|
Loading…
Reference in New Issue
Block a user