diff --git a/changes/bug26488 b/changes/bug26488 new file mode 100644 index 0000000000..f93d4c6f00 --- /dev/null +++ b/changes/bug26488 @@ -0,0 +1,4 @@ + o Major bugfixes (directory authority): + - Actually check that address we get from DirAuthority configuration + line is valid IPv4. Explicitly disallow DirAuthority adress to be + DNS hostname. Fixes bug 26488; bugfix on 0.1.2.10-rc. diff --git a/src/app/config/config.c b/src/app/config/config.c index 28d2be5ec1..665732ea56 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -6458,6 +6458,23 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, } addrport = smartlist_get(items, 0); smartlist_del_keeporder(items, 0); + + const char *addrport_sep = strchr(addrport, ':'); + if (!addrport_sep) { + log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' " + "(':' not found)", addrport); + goto err; + } + + address = tor_strndup(addrport, addrport_sep - addrport); + if (!string_is_valid_ipv4_address(address)) { + log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' " + "(invalid IPv4 address)", address); + goto err; + } + + tor_free(address); + if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) { log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'", addrport); goto err; diff --git a/src/test/test_config.c b/src/test/test_config.c index 596ae04482..af3a8a7cfe 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -1634,6 +1634,40 @@ test_config_parsing_trusted_dir_server(void *arg) #undef TEST_DIR_AUTH_LINE_END #undef TEST_DIR_AUTH_IPV6_FLAG +#define TEST_DIR_AUTH_LINE_START \ + "foobar orport=12345 " \ + "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " +#define TEST_DIR_AUTH_LINE_END_BAD_IP \ + "0.256.3.4:54321 " \ + "FDB2 FBD2 AAA5 25FA 2999 E617 5091 5A32 C777 3B17" +#define TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR \ + "torproject.org:54321 " \ + "FDB2 FBD2 AAA5 25FA 2999 E617 5091 5A32 C777 3B17" + +static void +test_config_parsing_invalid_dir_address(void *arg) +{ + (void)arg; + int rv; + + rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START + TEST_DIR_AUTH_LINE_END_BAD_IP, + V3_DIRINFO, 1); + tt_int_op(rv, OP_EQ, -1); + + rv = parse_dir_authority_line(TEST_DIR_AUTH_LINE_START + TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR, + V3_DIRINFO, 1); + tt_int_op(rv, OP_EQ, -1); + + done: + return; +} + +#undef TEST_DIR_AUTH_LINE_START +#undef TEST_DIR_AUTH_LINE_END_BAD_IP +#undef TEST_DIR_AUTH_LINE_END_WITH_DNS_ADDR + /* No secrets here: * id is `echo "syn-propanethial-S-oxide" | shasum | cut -d" " -f1` */ @@ -5698,6 +5732,7 @@ struct testcase_t config_tests[] = { CONFIG_TEST(adding_trusted_dir_server, TT_FORK), CONFIG_TEST(adding_fallback_dir_server, TT_FORK), CONFIG_TEST(parsing_trusted_dir_server, 0), + CONFIG_TEST(parsing_invalid_dir_address, 0), CONFIG_TEST(parsing_fallback_dir_server, 0), CONFIG_TEST(adding_default_trusted_dir_servers, TT_FORK), CONFIG_TEST(adding_dir_servers, TT_FORK),