]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
net: Reject invalid characters in port ranges
authorc <c@chroniko.jp>
Fri, 9 Oct 2020 03:10:24 +0000 (03:10 +0000)
committerDavid Goulet <dgoulet@torproject.org>
Mon, 4 Oct 2021 19:19:16 +0000 (15:19 -0400)
Fixes issue #22469 where port strings such as '0x00' get accepted, not
because the string gets converted to hex, but because the string is
silently truncated past the invalid character 'x'. This also causes
issues for strings such as '0x01-0x02' which look like a hex port range,
but in reality gets truncated to '0', which is definitely not what a
user intends.

Warn and reject such port strings as invalid.

Also, since we're throwing that "malformed port" warning a lot in the
function, wrap it up in a nice goto.

Fixes #22469

src/lib/net/address.c
src/test/test_address.c

index 26b155bc4cbc0b8273519851001595276443a16e..085eb8c458c0a6f2218c3eb1fef67f0b52b053c1 100644 (file)
@@ -2005,20 +2005,15 @@ parse_port_range(const char *port, uint16_t *port_min_out,
     char *endptr = NULL;
     port_min = (int)tor_parse_long(port, 10, 0, 65535, &ok, &endptr);
     if (!ok) {
-      log_warn(LD_GENERAL,
-               "Malformed port %s on address range; rejecting.",
-               escaped(port));
-      return -1;
-    } else if (endptr && *endptr == '-') {
+      goto malformed_port;
+    } else if (endptr && *endptr != '\0') {
+      if (*endptr != '-')
+        goto malformed_port;
       port = endptr+1;
       endptr = NULL;
       port_max = (int)tor_parse_long(port, 10, 1, 65535, &ok, &endptr);
-      if (!ok) {
-        log_warn(LD_GENERAL,
-                 "Malformed port %s on address range; rejecting.",
-                 escaped(port));
-        return -1;
-      }
+      if (!ok)
+        goto malformed_port;
     } else {
       port_max = port_min;
     }
@@ -2037,6 +2032,11 @@ parse_port_range(const char *port, uint16_t *port_min_out,
   *port_max_out = (uint16_t) port_max;
 
   return 0;
+ malformed_port:
+  log_warn(LD_GENERAL,
+           "Malformed port %s on address range; rejecting.",
+           escaped(port));
+  return -1;
 }
 
 /** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
index 9c1415419c0ec5256542a3814ed09ec842a65ffe..015ca0807cce86b1cf5343df3458cb6f82a74869 100644 (file)
@@ -1326,6 +1326,42 @@ test_address_dirserv_router_addr_private(void *opt_dir_allow_private)
   UNMOCK(get_options);
 }
 
+static void
+test_address_parse_port_range(void *arg)
+{
+  int ret;
+  uint16_t min_out = 0;
+  uint16_t max_out = 0;
+
+  (void) arg;
+
+  /* Invalid. */
+  ret = parse_port_range("0x00", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, -1);
+  ret = parse_port_range("0x01", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, -1);
+  ret = parse_port_range("1817161", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, -1);
+  ret = parse_port_range("65536", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, -1);
+  ret = parse_port_range("1-65536", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, -1);
+
+  /* Valid. */
+  ret = parse_port_range("65535", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, 0);
+  tt_int_op(min_out, OP_EQ, 65535);
+  tt_int_op(max_out, OP_EQ, 65535);
+
+  ret = parse_port_range("1-65535", &min_out, &max_out);
+  tt_int_op(ret, OP_EQ, 0);
+  tt_int_op(min_out, OP_EQ, 1);
+  tt_int_op(max_out, OP_EQ, 65535);
+
+ done:
+  ;
+}
+
 #define ADDRESS_TEST(name, flags) \
   { #name, test_address_ ## name, flags, NULL, NULL }
 #define ADDRESS_TEST_STR_ARG(name, flags, str_arg) \
@@ -1364,5 +1400,6 @@ struct testcase_t address_tests[] = {
   ADDRESS_TEST(tor_node_in_same_network_family, 0),
   ADDRESS_TEST(dirserv_router_addr_private, 0),
   ADDRESS_TEST_STR_ARG(dirserv_router_addr_private, 0, "allow_private"),
+  ADDRESS_TEST(parse_port_range, 0),
   END_OF_TESTCASES
 };