Skip to content

Commit 0cd9273

Browse files
committed
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.
1 parent 94c9015 commit 0cd9273

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
@@ -83,6 +83,9 @@ Low-level RPC changes
8383
* `getwalletinfo`
8484
* `getmininginfo`
8585

86+
- `dumpwallet` no longer allows overwriting files. This is a security measure
87+
as well as prevents dangerous user mistakes.
88+
8689
Credits
8790
=======
8891

src/wallet/rpcdump.cpp

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

617617
EnsureWalletIsUnlocked(pwallet);
618618

619-
std::ofstream file;
620619
boost::filesystem::path filepath = request.params[0].get_str();
621620
filepath = boost::filesystem::absolute(filepath);
621+
622+
/* Prevent arbitrary files from being overwritten. There have been reports
623+
* that users have overwritten wallet files this way:
624+
* https://github.com/bitcoin/bitcoin/issues/9934
625+
* It may also avoid other security issues.
626+
*/
627+
if (boost::filesystem::exists(filepath)) {
628+
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");
629+
}
630+
631+
std::ofstream file;
622632
file.open(filepath.string().c_str());
623633
if (!file.is_open())
624634
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):
@@ -105,5 +105,8 @@ def run_test (self):
105105
assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now
106106
assert_equal(found_addr_rsv, 90*2)
107107

108+
# Overwriting should fail
109+
assert_raises_jsonrpc(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump")
110+
108111
if __name__ == '__main__':
109112
WalletDumpTest().main ()

0 commit comments

Comments
 (0)