Merge bitcoin/bitcoin#29521: cli: Detect port errors in rpcconnect and rpcport

24bc46c83b cli: Add warning for duplicate port definition (tdb3)
e208fb5d3b cli: Sanitize ports in rpcconnect and rpcport (tdb3)

Pull request description:

  Adds invalid port detection to bitcoin-cli for -rpcconnect and -rpcport.

  In addition to detecting malformed/invalid ports (e.g. those outside of the 16-bit port range, not numbers, etc.), bitcoin-cli also now considers usage of port 0 to be invalid.  bitcoin-cli previously considered port 0 to be valid and attempted to use it to reach bitcoind.

  Functional tests were added for invalid port detection as well as port prioritization.
  Additionally, a warning is provided when a port is specified in both -rpcconnect and -rpcport.

  This PR is an alternate approach to PR #27820 (e.g. SplitHostPort is unmodified).

  Considered an alternative to 127.0.0.1 being specified in functional tests, but at first glance, this might need an update to test_framework/util.py (e.g.  rpc_url), which might be left to a future PR.

ACKs for top commit:
  S3RK:
    light code review ACK 24bc46c83b
  achow101:
    ACK 24bc46c83b
  cbergqvist:
    re ACK 24bc46c83b

Tree-SHA512: c83ab6a30a08dd1ac8b368a7dcc2b4f23170f0b61dd67ffcad7bcda05096d333bcb9821fba11018151f55b2929c0a333bfec15b8bb863d83f41fc1974c6efca5
This commit is contained in:
Ava Chow
2024-06-11 15:55:18 -04:00
2 changed files with 84 additions and 2 deletions

View File

@@ -743,8 +743,41 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
// 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
// 3. default port for chain
uint16_t port{BaseParams().RPCPort()};
SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
port = static_cast<uint16_t>(gArgs.GetIntArg("-rpcport", port));
{
uint16_t rpcconnect_port{0};
const std::string rpcconnect_str = gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
if (!SplitHostPort(rpcconnect_str, rpcconnect_port, host)) {
// Uses argument provided as-is
// (rather than value parsed)
// to aid the user in troubleshooting
throw std::runtime_error(strprintf("Invalid port provided in -rpcconnect: %s", rpcconnect_str));
} else {
if (rpcconnect_port != 0) {
// Use the valid port provided in rpcconnect
port = rpcconnect_port;
} // else, no port was provided in rpcconnect (continue using default one)
}
if (std::optional<std::string> rpcport_arg = gArgs.GetArg("-rpcport")) {
// -rpcport was specified
const uint16_t rpcport_int{ToIntegral<uint16_t>(rpcport_arg.value()).value_or(0)};
if (rpcport_int == 0) {
// Uses argument provided as-is
// (rather than value parsed)
// to aid the user in troubleshooting
throw std::runtime_error(strprintf("Invalid port provided in -rpcport: %s", rpcport_arg.value()));
}
// Use the valid port provided
port = rpcport_int;
// If there was a valid port provided in rpcconnect,
// rpcconnect_port is non-zero.
if (rpcconnect_port != 0) {
tfm::format(std::cerr, "Warning: Port specified in both -rpcconnect and -rpcport. Using -rpcport %u\n", port);
}
}
}
// Obtain event base
raii_event_base base = obtain_event_base();