From ab55776189006b150d12165714dc035e18fb94af Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 30 Dec 2020 12:02:57 -0300 Subject: [PATCH] hide password in -stdin `walletpassphrase` command --- src/bitcoin-cli.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 146034dc7..937717e17 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -19,6 +19,13 @@ #include +#ifdef WIN32 +#include +#else +#include +#include +#endif + const std::function G_TRANSLATION_FUN = nullptr; static const char DEFAULT_RPCCONNECT[] = "127.0.0.1"; @@ -32,6 +39,7 @@ std::string HelpMessageCli() strUsage += HelpMessageOpt("-?", _("This help message")); strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME)); strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); + strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). If first extra argument is `walletpassphrase` then the first line(password) will not be echoed.")); AppendParamsHelpMessages(strUsage); strUsage += HelpMessageOpt("-rpcconnect=", strprintf(_("Send commands to node running on (default: %s)"), DEFAULT_RPCCONNECT)); strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Connect to JSON-RPC on (default: %u or testnet: %u)"), 8232, 18232)); @@ -39,7 +47,6 @@ std::string HelpMessageCli() strUsage += HelpMessageOpt("-rpcuser=", _("Username for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcclienttimeout=", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT)); - strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)")); return strUsage; } @@ -263,6 +270,32 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params) return reply; } +void SetStdinEcho(bool enable = true) +{ +#ifdef WIN32 + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode; + GetConsoleMode(hStdin, &mode); + + if (!enable) + mode &= ~ENABLE_ECHO_INPUT; + else + mode |= ENABLE_ECHO_INPUT; + + SetConsoleMode(hStdin, mode); + +#else + struct termios tty; + tcgetattr(STDIN_FILENO, &tty); + if (!enable) + tty.c_lflag &= ~ECHO; + else + tty.c_lflag |= ECHO; + + (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty); +#endif +} + int CommandLineRPC(int argc, char *argv[]) { std::string strPrint; @@ -275,10 +308,21 @@ int CommandLineRPC(int argc, char *argv[]) } std::vector args = std::vector(&argv[1], &argv[argc]); if (GetBoolArg("-stdin", false)) { + bool hide = false; + if (strncmp(argv[1], "walletpassphrase", 16) == 0) { + SetStdinEcho(false); + hide = true; + } + // Read one arg per line from stdin and append std::string line; - while (std::getline(std::cin,line)) + while (std::getline(std::cin,line)) { args.push_back(line); + if (hide) { + SetStdinEcho(true); + hide = false; + } + } } if (args.size() < 1) throw std::runtime_error("too few parameters (need at least command)");