You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
5.0 KiB
101 lines
5.0 KiB
3 years ago
|
#!/usr/bin/env python3
|
||
|
# Copyright (c) 2017-2019 The Bitcoin Core developers
|
||
|
# Distributed under the MIT software license, see the accompanying
|
||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||
|
"""
|
||
|
A test for RPC users with restricted permissions
|
||
|
"""
|
||
|
from test_framework.test_framework import BitcoinTestFramework
|
||
|
import os
|
||
|
from test_framework.util import (
|
||
|
get_datadir_path,
|
||
|
assert_equal,
|
||
|
str_to_b64str
|
||
|
)
|
||
|
import http.client
|
||
|
import urllib.parse
|
||
|
|
||
|
def rpccall(node, user, method):
|
||
|
url = urllib.parse.urlparse(node.url)
|
||
|
headers = {"Authorization": "Basic " + str_to_b64str('{}:{}'.format(user[0], user[3]))}
|
||
|
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||
|
conn.connect()
|
||
|
conn.request('POST', '/', '{"method": "' + method + '"}', headers)
|
||
|
resp = conn.getresponse()
|
||
|
conn.close()
|
||
|
return resp
|
||
|
|
||
|
|
||
|
class RPCWhitelistTest(BitcoinTestFramework):
|
||
|
def set_test_params(self):
|
||
|
self.num_nodes = 1
|
||
|
|
||
|
def setup_chain(self):
|
||
|
super().setup_chain()
|
||
|
# 0 => Username
|
||
|
# 1 => Password (Hashed)
|
||
|
# 2 => Permissions
|
||
|
# 3 => Password Plaintext
|
||
|
self.users = [
|
||
|
["user1", "50358aa884c841648e0700b073c32b2e$b73e95fff0748cc0b517859d2ca47d9bac1aa78231f3e48fa9222b612bd2083e", "getbestblockhash,getblockcount,", "12345"],
|
||
|
["user2", "8650ba41296f62092377a38547f361de$4620db7ba063ef4e2f7249853e9f3c5c3592a9619a759e3e6f1c63f2e22f1d21", "getblockcount", "54321"]
|
||
|
]
|
||
|
# For exceptions
|
||
|
self.strange_users = [
|
||
|
# Test empty
|
||
|
["strangedude", "62d67dffec03836edd698314f1b2be62$c2fb4be29bb0e3646298661123cf2d8629640979cabc268ef05ea613ab54068d", ":", "s7R4nG3R7H1nGZ"],
|
||
|
["strangedude2", "575c012c7fe4b1e83b9d809412da3ef7$09f448d0acfc19924dd62ecb96004d3c2d4b91f471030dfe43c6ea64a8f658c1", "", "s7R4nG3R7H1nGZ"],
|
||
|
# Test trailing comma
|
||
|
["strangedude3", "23189c561b5975a56f4cf94030495d61$3a2f6aac26351e2257428550a553c4c1979594e36675bbd3db692442387728c0", ":getblockcount,", "s7R4nG3R7H1nGZ"],
|
||
|
# Test overwrite
|
||
|
["strangedude4", "990c895760a70df83949e8278665e19a$8f0906f20431ff24cb9e7f5b5041e4943bdf2a5c02a19ef4960dcf45e72cde1c", ":getblockcount, getbestblockhash", "s7R4nG3R7H1nGZ"],
|
||
|
["strangedude4", "990c895760a70df83949e8278665e19a$8f0906f20431ff24cb9e7f5b5041e4943bdf2a5c02a19ef4960dcf45e72cde1c", ":getblockcount", "s7R4nG3R7H1nGZ"],
|
||
|
# Testing the same permission twice
|
||
|
["strangedude5", "d12c6e962d47a454f962eb41225e6ec8$2dd39635b155536d3c1a2e95d05feff87d5ba55f2d5ff975e6e997a836b717c9", ":getblockcount,getblockcount", "s7R4nG3R7H1nGZ"]
|
||
|
]
|
||
|
# These commands shouldn't be allowed for any user to test failures
|
||
|
self.never_allowed = ["getnetworkinfo"]
|
||
|
with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f:
|
||
|
f.write("\nrpcwhitelistdefault=0\n")
|
||
|
for user in self.users:
|
||
|
f.write("rpcauth=" + user[0] + ":" + user[1] + "\n")
|
||
|
f.write("rpcwhitelist=" + user[0] + ":" + user[2] + "\n")
|
||
|
# Special cases
|
||
|
for strangedude in self.strange_users:
|
||
|
f.write("rpcauth=" + strangedude[0] + ":" + strangedude[1] + "\n")
|
||
|
f.write("rpcwhitelist=" + strangedude[0] + strangedude[2] + "\n")
|
||
|
|
||
|
|
||
|
def run_test(self):
|
||
|
for user in self.users:
|
||
|
permissions = user[2].replace(" ", "").split(",")
|
||
|
# Pop all empty items
|
||
|
i = 0
|
||
|
while i < len(permissions):
|
||
|
if permissions[i] == '':
|
||
|
permissions.pop(i)
|
||
|
|
||
|
i += 1
|
||
|
for permission in permissions:
|
||
|
self.log.info("[" + user[0] + "]: Testing a permitted permission (" + permission + ")")
|
||
|
assert_equal(200, rpccall(self.nodes[0], user, permission).status)
|
||
|
for permission in self.never_allowed:
|
||
|
self.log.info("[" + user[0] + "]: Testing a non permitted permission (" + permission + ")")
|
||
|
assert_equal(403, rpccall(self.nodes[0], user, permission).status)
|
||
|
# Now test the strange users
|
||
|
for permission in self.never_allowed:
|
||
|
self.log.info("Strange test 1")
|
||
|
assert_equal(403, rpccall(self.nodes[0], self.strange_users[0], permission).status)
|
||
|
for permission in self.never_allowed:
|
||
|
self.log.info("Strange test 2")
|
||
|
assert_equal(403, rpccall(self.nodes[0], self.strange_users[1], permission).status)
|
||
|
self.log.info("Strange test 3")
|
||
|
assert_equal(200, rpccall(self.nodes[0], self.strange_users[2], "getblockcount").status)
|
||
|
self.log.info("Strange test 4")
|
||
|
assert_equal(403, rpccall(self.nodes[0], self.strange_users[3], "getbestblockhash").status)
|
||
|
self.log.info("Strange test 5")
|
||
|
assert_equal(200, rpccall(self.nodes[0], self.strange_users[4], "getblockcount").status)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
RPCWhitelistTest().main()
|