-
Notifications
You must be signed in to change notification settings - Fork 37.7k
wallet: Replace %w by wallet name in -walletnotify script #13339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/wallet/wallet.cpp
Outdated
@@ -988,6 +988,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) | |||
if (!strCmd.empty()) | |||
{ | |||
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); | |||
boost::replace_all(strCmd, "%w", GetName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the wallet name can contain any character, we need shell-escaping here.
@laanwj see 4fa29f8, what would be the solution in that case? only escape |
Concept ACK - seems like a nice consideration |
The best way would be to use an invocation (use one of the Lacking that, you can escape for bash and most other shells by surrounding with It's extremely important to be careful about this, I have seen terrible things happen due to unproperly escaped shell input, and I will NACK this unless this is addressed. |
@laanwj |
Agree. Right - things to test would be |
4fa29f8
to
764ee97
Compare
I don't understand what you mean. You suggest the wallet name can have |
Yes, those sequences could be part of the wallet name. They are the typical ways to fool shell escaping and do arbitrary command execution, so I suggested them for testing whether shell escaping is working as expected. |
Not sure if we want to further extend walletnotify. |
IMO we should consider adding this to fully support multi wallets without taking into account #13262. For existing systems that are based on |
I think it's fine to add this to walletnotify, too. Agree that another notification system would be better, but this is useful to users in the short term. It's is a small change to the code. |
Needs rebase due to merge of #13341 |
764ee97
to
cef0327
Compare
src/wallet/wallet.cpp
Outdated
@@ -988,6 +988,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) | |||
if (!strCmd.empty()) | |||
{ | |||
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); | |||
std::string name = GetName(); | |||
boost::replace_all(name, "'", "'\''"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please factor this out to a function ShellEscape
which does boost::replace_all(name, "'", "'\''");; return "'" + name + "'"
. We might need that in other places at some point, and it makes it an easier to review unit.
(also it's possible that for WIN32/cmd this needs something else?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
@@ -24,7 +24,8 @@ def setup_network(self): | |||
"-blocknotify=echo %%s >> %s" % self.block_filename], | |||
["-blockversion=211", | |||
"-rescan", | |||
"-walletnotify=echo %%s >> %s" % self.tx_filename]] | |||
"-wallet=t- 1", | |||
"-walletnotify=echo %%w\:%%s >> %s" % self.tx_filename]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would work even without %w properly escaped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could just use '...%w\:%s >> {}'.format(self.tx_filename)
to avoid this confusion.
Needs rebase and comments addressed. |
LGTM cef0327 but yeah needs rebase + comments addressed 👍 |
cef0327
to
4132f02
Compare
@promag This no longer compiles:
Perhaps a good opportunity to get rid of |
0292b09
to
f43c5e2
Compare
f43c5e2
to
c8843e4
Compare
|
||
class NotificationsTest(BitcoinTestFramework): | ||
def set_test_params(self): | ||
self.num_nodes = 2 | ||
self.setup_clean_chain = True | ||
|
||
def setup_network(self): | ||
self.wallet = ''.join(chr(i) for i in range(FILE_CHAR_START, FILE_CHAR_END) if chr(i) not in FILE_CHAR_BLACKLIST) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe prefix it with "wallet" so you can tab-complete if you ever need to touch it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks potentially dangerous...
Maybe prefix it with "wallet" so you can tab-complete if you ever need to touch it...
I like luke's suggestion to prefix with something. Maybe a prefix like "feature_notifications" to give a hint where the file comes from, and to help with tab completion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just prefixed with not yetwallet
.
ACK 8267184 |
BTW #17878 adds support for wallet ZMQ notifications which include the wallet name. |
src/wallet/wallet.cpp
Outdated
@@ -1156,6 +1156,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) | |||
if (!strCmd.empty()) | |||
{ | |||
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); | |||
#ifdef WIN32 | |||
boost::replace_all(strCmd, "%w", GetName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is unsafe since it can corrupt wallet names and trigger arbitrary shell commands to run from an RPC. Suggested fix from previous thread #13339 (comment) is 26e0017
e19d9c1
to
1c335d5
Compare
Thanks @ryanofsky, rebased, squashed and added you as co author. Updated test to take into account behavior difference in windows. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK a89a170
|
||
class NotificationsTest(BitcoinTestFramework): | ||
def set_test_params(self): | ||
self.num_nodes = 2 | ||
self.setup_clean_chain = True | ||
|
||
def setup_network(self): | ||
self.wallet = ''.join(chr(i) for i in range(FILE_CHAR_START, FILE_CHAR_END) if chr(i) not in FILE_CHAR_BLACKLIST) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks potentially dangerous...
Maybe prefix it with "wallet" so you can tab-complete if you ever need to touch it...
I like luke's suggestion to prefix with something. Maybe a prefix like "feature_notifications" to give a hint where the file comes from, and to help with tab completion
@@ -13,13 +13,19 @@ | |||
connect_nodes, | |||
) | |||
|
|||
# Linux allow all characters other than \x00 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even with various locales? How is Unicode handled?
Should be no issue here. This remains in unicode and utf8 formats until it hits bitcoin filesystem code which uses utf8 directly on non-windows systems, and converts to wide characters for windows apis.
# Windows disallow control characters (0-31) and /\?%:|"<> | ||
FILE_CHAR_START = 32 if os.name == 'nt' else 1 | ||
FILE_CHAR_END = 128 | ||
FILE_CHAR_BLACKLIST = '/\\?%*:|"<>' if os.name == 'nt' else '/' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about macOS, BSD, Amiga, etc?
Would be nice to autodetect this in the test.
It shouldn't be too hard to autodetect by just writing to files and seeing what succeeds, but in the worst case this test just doesn't work on an obscure platform and the fix is trivial, so I don't think it's is a big deal
Linux Tested ACK 1c335d5 |
Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
1c335d5
to
56d2307
Compare
56d2307
to
4e9efac
Compare
Replaced with @ryanofsky amended commit. |
ACK 4e9efac |
4e9efac test: Check wallet name in -walletnotify script (João Barbosa) 9a5b5ee wallet: Replace %w by wallet name in -walletnotify script (João Barbosa) Pull request description: Fixes #13237. ACKs for top commit: laanwj: ACK 4e9efac Tree-SHA512: 189dd1c785485f2e974d7c12531851b2a977778b3b954aa95efd527322ba3345924cfd587fb9c90b0fa979202af0ab2d90e53d125fe266a36c94f757e4176203
…fy script 4e9efac test: Check wallet name in -walletnotify script (João Barbosa) 9a5b5ee wallet: Replace %w by wallet name in -walletnotify script (João Barbosa) Pull request description: Fixes bitcoin#13237. ACKs for top commit: laanwj: ACK 4e9efac Tree-SHA512: 189dd1c785485f2e974d7c12531851b2a977778b3b954aa95efd527322ba3345924cfd587fb9c90b0fa979202af0ab2d90e53d125fe266a36c94f757e4176203
…cript Summary: test: Check wallet name in -walletnotify script (João Barbosa) wallet: Replace %w by wallet name in -walletnotify script (João Barbosa) Pull request description: Fixes #13237. https://github.com/bitcoin/bitcoin/pull/13339/files --- Backport of Core [[bitcoin/bitcoin#13339 | PR13339]] Test Plan: ninja all check check-functional Reviewers: #bitcoin_abc, PiRK Reviewed By: PiRK Differential Revision: https://reviews.bitcoinabc.org/D8129
…fy script 4e9efac test: Check wallet name in -walletnotify script (João Barbosa) 9a5b5ee wallet: Replace %w by wallet name in -walletnotify script (João Barbosa) Pull request description: Fixes bitcoin#13237. ACKs for top commit: laanwj: ACK 4e9efac Tree-SHA512: 189dd1c785485f2e974d7c12531851b2a977778b3b954aa95efd527322ba3345924cfd587fb9c90b0fa979202af0ab2d90e53d125fe266a36c94f757e4176203
Fixes #13237.