Skip to content

Commit 0452678

Browse files
amadeuszpawlikAmadeusz Pawlik
authored andcommitted
Validate port options
Check `port` options for invalid values (ports are parsed as uint16, so in practice values >65535 are invalid; port 0 is undefined and therefore considered invalid too). This allows for an early rejection of faulty values and an supplying an informative message to the user. Splits tests in `feature_proxy.py` to cover both invalid `hostname` and `port` values. Adds a release-note as previously valid `-port` and `-rpcport` values can now result in errors.
1 parent f8387c4 commit 0452678

File tree

5 files changed

+80
-9
lines changed

5 files changed

+80
-9
lines changed

doc/release-notes-22087.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Updated settings
2+
----------------
3+
4+
- Ports specified in `-port` and `-rpcport` options are now validated at startup. Values that previously worked and were considered valid can now result in errors. (#22087)

src/init.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,51 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
12551255
// as they would never get updated.
12561256
if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(args));
12571257

1258+
// Check port numbers
1259+
for (const std::string port_option : {
1260+
"-port",
1261+
"-rpcport",
1262+
}) {
1263+
if (args.IsArgSet(port_option)) {
1264+
const std::string port = args.GetArg(port_option, "");
1265+
uint16_t n;
1266+
if (!ParseUInt16(port, &n) || n == 0) {
1267+
return InitError(InvalidPortErrMsg(port_option, port));
1268+
}
1269+
}
1270+
}
1271+
1272+
for (const std::string port_option : {
1273+
"-i2psam",
1274+
"-onion",
1275+
"-proxy",
1276+
"-rpcbind",
1277+
"-torcontrol",
1278+
"-whitebind",
1279+
"-zmqpubhashblock",
1280+
"-zmqpubhashtx",
1281+
"-zmqpubrawblock",
1282+
"-zmqpubrawtx",
1283+
"-zmqpubsequence",
1284+
}) {
1285+
for (const std::string& socket_addr : args.GetArgs(port_option)) {
1286+
std::string host_out;
1287+
uint16_t port_out{0};
1288+
if (!SplitHostPort(socket_addr, port_out, host_out)) {
1289+
return InitError(InvalidPortErrMsg(port_option, socket_addr));
1290+
}
1291+
}
1292+
}
1293+
1294+
for (const std::string& socket_addr : args.GetArgs("-bind")) {
1295+
std::string host_out;
1296+
uint16_t port_out{0};
1297+
std::string bind_socket_addr = socket_addr.substr(0, socket_addr.rfind('='));
1298+
if (!SplitHostPort(bind_socket_addr, port_out, host_out)) {
1299+
return InitError(InvalidPortErrMsg("-bind", socket_addr));
1300+
}
1301+
}
1302+
12581303
// sanitize comments per BIP-0014, format user agent and check total size
12591304
std::vector<std::string> uacomments;
12601305
for (const std::string& cmt : args.GetArgs("-uacomment")) {

src/util/error.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBi
4949
return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
5050
}
5151

52+
bilingual_str InvalidPortErrMsg(const std::string& optname, const std::string& invalid_value)
53+
{
54+
return strprintf(_("Invalid port specified in %s: '%s'"), optname, invalid_value);
55+
}
56+
5257
bilingual_str AmountHighWarn(const std::string& optname)
5358
{
5459
return strprintf(_("%s is set very high!"), optname);

src/util/error.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ bilingual_str TransactionErrorString(const TransactionError error);
3939

4040
bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind);
4141

42+
bilingual_str InvalidPortErrMsg(const std::string& optname, const std::string& strPort);
43+
4244
bilingual_str AmountHighWarn(const std::string& optname);
4345

4446
bilingual_str AmountErrMsg(const std::string& optname, const std::string& strValue);

test/functional/feature_proxy.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -317,19 +317,34 @@ def networks_dict(d):
317317

318318
self.stop_node(1)
319319

320-
self.log.info("Test passing invalid -proxy raises expected init error")
321-
self.nodes[1].extra_args = ["-proxy=abc:def"]
322-
msg = "Error: Invalid -proxy address or hostname: 'abc:def'"
320+
self.log.info("Test passing invalid -proxy hostname raises expected init error")
321+
self.nodes[1].extra_args = ["-proxy=abc..abc:23456"]
322+
msg = "Error: Invalid -proxy address or hostname: 'abc..abc:23456'"
323323
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
324324

325-
self.log.info("Test passing invalid -onion raises expected init error")
326-
self.nodes[1].extra_args = ["-onion=xyz:abc"]
327-
msg = "Error: Invalid -onion address or hostname: 'xyz:abc'"
325+
self.log.info("Test passing invalid -proxy port raises expected init error")
326+
self.nodes[1].extra_args = ["-proxy=192.0.0.1:def"]
327+
msg = "Error: Invalid port specified in -proxy: '192.0.0.1:def'"
328328
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
329329

330-
self.log.info("Test passing invalid -i2psam raises expected init error")
331-
self.nodes[1].extra_args = ["-i2psam=def:xyz"]
332-
msg = "Error: Invalid -i2psam address or hostname: 'def:xyz'"
330+
self.log.info("Test passing invalid -onion hostname raises expected init error")
331+
self.nodes[1].extra_args = ["-onion=xyz..xyz:23456"]
332+
msg = "Error: Invalid -onion address or hostname: 'xyz..xyz:23456'"
333+
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
334+
335+
self.log.info("Test passing invalid -onion port raises expected init error")
336+
self.nodes[1].extra_args = ["-onion=192.0.0.1:def"]
337+
msg = "Error: Invalid port specified in -onion: '192.0.0.1:def'"
338+
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
339+
340+
self.log.info("Test passing invalid -i2psam hostname raises expected init error")
341+
self.nodes[1].extra_args = ["-i2psam=def..def:23456"]
342+
msg = "Error: Invalid -i2psam address or hostname: 'def..def:23456'"
343+
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
344+
345+
self.log.info("Test passing invalid -i2psam port raises expected init error")
346+
self.nodes[1].extra_args = ["-i2psam=192.0.0.1:def"]
347+
msg = "Error: Invalid port specified in -i2psam: '192.0.0.1:def'"
333348
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
334349

335350
self.log.info("Test passing invalid -onlynet=i2p without -i2psam raises expected init error")

0 commit comments

Comments
 (0)