Skip to content

Commit a43be5b

Browse files
laanwjMarcoFalke
authored andcommitted
rpc: Prevent dumpwallet from overwriting files
Prevent arbitrary files from being overwritten. There have been reports that users have overwritten wallet files this way. It may also avoid other security issues. Fixes #9934. Adds mention to release notes and adds a test. Github-Pull: #9937 Rebased-From: 0cd9273
1 parent b6c0209 commit a43be5b

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

doc/release-notes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ Notable changes
6565
0.15.1 Change log
6666
=================
6767

68+
- `dumpwallet` no longer allows overwriting files. This is a security measure
69+
as well as prevents dangerous user mistakes.
70+
6871
Credits
6972
=======
7073

src/wallet/rpcdump.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
595595
if (request.fHelp || request.params.size() != 1)
596596
throw std::runtime_error(
597597
"dumpwallet \"filename\"\n"
598-
"\nDumps all wallet keys in a human-readable format.\n"
598+
"\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n"
599599
"\nArguments:\n"
600600
"1. \"filename\" (string, required) The filename with path (either absolute or relative to bitcoind)\n"
601601
"\nResult:\n"
@@ -611,9 +611,19 @@ UniValue dumpwallet(const JSONRPCRequest& request)
611611

612612
EnsureWalletIsUnlocked(pwallet);
613613

614-
std::ofstream file;
615614
boost::filesystem::path filepath = request.params[0].get_str();
616615
filepath = boost::filesystem::absolute(filepath);
616+
617+
/* Prevent arbitrary files from being overwritten. There have been reports
618+
* that users have overwritten wallet files this way:
619+
* https://github.com/bitcoin/bitcoin/issues/9934
620+
* It may also avoid other security issues.
621+
*/
622+
if (boost::filesystem::exists(filepath)) {
623+
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
624+
}
625+
626+
std::ofstream file;
617627
file.open(filepath.string().c_str());
618628
if (!file.is_open())
619629
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");

test/functional/wallet-dump.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import os
88

99
from test_framework.test_framework import BitcoinTestFramework
10-
from test_framework.util import assert_equal
10+
from test_framework.util import (assert_equal, assert_raises_jsonrpc)
1111

1212

1313
def read_dump(file_name, addrs, hd_master_addr_old):
@@ -108,5 +108,8 @@ def run_test (self):
108108
assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now
109109
assert_equal(found_addr_rsv, 90*2)
110110

111+
# Overwriting should fail
112+
assert_raises_jsonrpc(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump")
113+
111114
if __name__ == '__main__':
112115
WalletDumpTest().main ()

0 commit comments

Comments
 (0)