diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-10-03 16:32:00 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-10-04 15:43:20 -0400 |
commit | 05aed5b635fa7148fe2a4ea87e7296fa6bec3087 (patch) | |
tree | f45449d1ee6666ed094cd0afed4f158099f2e31d /src | |
parent | 684500519d5060fcbcc410a0e71d8d9a32fa8220 (diff) | |
download | tor-05aed5b635fa7148fe2a4ea87e7296fa6bec3087.tar.gz tor-05aed5b635fa7148fe2a4ea87e7296fa6bec3087.zip |
Allow a unix: address to contain a C-style quoted string.
Feature 18753 -- all this to allow spaces.
Diffstat (limited to 'src')
-rw-r--r-- | src/common/util.c | 2 | ||||
-rw-r--r-- | src/common/util.h | 1 | ||||
-rw-r--r-- | src/or/config.c | 137 | ||||
-rw-r--r-- | src/or/config.h | 6 | ||||
-rw-r--r-- | src/or/rendservice.c | 32 | ||||
-rw-r--r-- | src/test/test_config.c | 192 | ||||
-rw-r--r-- | src/test/test_controller.c | 49 |
7 files changed, 339 insertions, 80 deletions
diff --git a/src/common/util.c b/src/common/util.c index 259ff8756f..c632ee498e 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2906,7 +2906,7 @@ read_file_to_str, (const char *filename, int flags, struct stat *stat_out)) * provided), and return a pointer to the position in <b>s</b> immediately * after the string. On failure, return NULL. */ -static const char * +const char * unescape_string(const char *s, char **result, size_t *size_out) { const char *cp; diff --git a/src/common/util.h b/src/common/util.h index 57605ccfd1..479fc8d610 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -385,6 +385,7 @@ MOCK_DECL_ATTR(char *, read_file_to_str, char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) ATTR_MALLOC; +const char *unescape_string(const char *s, char **result, size_t *size_out); const char *parse_config_line_from_str_verbose(const char *line, char **key_out, char **value_out, const char **err_out); diff --git a/src/or/config.c b/src/or/config.c index 18cbe34be3..ff43486084 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -68,6 +68,9 @@ /* Prefix used to indicate a Unix socket in a FooPort configuration. */ static const char unix_socket_prefix[] = "unix:"; +/* Prefix used to indicate a Unix socket with spaces in it, in a FooPort + * configuration. */ +static const char unix_q_socket_prefix[] = "unix:\""; /** A list of abbreviations and aliases to map command-line options, obsolete * option names, or alternative option names, to their current values. */ @@ -6288,54 +6291,61 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid_nonlocal) } SMARTLIST_FOREACH_END(port); } -#ifdef HAVE_SYS_UN_H - -/** Parse the given <b>addrport</b> and set <b>path_out</b> if a Unix socket - * path is found. Return 0 on success. On error, a negative value is - * returned, -ENOENT if no Unix statement found, -EINVAL if the socket path - * is empty and -ENOSYS if AF_UNIX is not supported (see function in the - * #else statement below). */ - -int -config_parse_unix_port(const char *addrport, char **path_out) -{ - tor_assert(path_out); - tor_assert(addrport); - - if (strcmpstart(addrport, unix_socket_prefix)) { - /* Not a Unix socket path. */ - return -ENOENT; - } - - if (strlen(addrport + strlen(unix_socket_prefix)) == 0) { - /* Empty socket path, not very usable. */ - return -EINVAL; - } - - *path_out = tor_strdup(addrport + strlen(unix_socket_prefix)); - return 0; -} - -#else /* defined(HAVE_SYS_UN_H) */ - +/** + * Take a string (<b>line</b>) that begins with either an address:port, a + * port, or an AF_UNIX address, optionally quoted, prefixed with + * "unix:". Parse that line, and on success, set <b>addrport_out</b> to a new + * string containing the beginning portion (without prefix). Iff there was a + * unix: prefix, set <b>is_unix_out</b> to true. On success, also set + * <b>rest_out</b> to point to the part of the line after the address portion. + * + * Return 0 on success, -1 on failure. + */ int -config_parse_unix_port(const char *addrport, char **path_out) +port_cfg_line_extract_addrport(const char *line, + char **addrport_out, + int *is_unix_out, + const char **rest_out) { - tor_assert(path_out); - tor_assert(addrport); + tor_assert(line); + tor_assert(addrport_out); + tor_assert(is_unix_out); + tor_assert(rest_out); + + line = eat_whitespace(line); + + if (!strcmpstart(line, unix_q_socket_prefix)) { + // It starts with unix:" + size_t sz; + *is_unix_out = 1; + *addrport_out = NULL; + line += strlen(unix_socket_prefix); /*No q: Keep the quote */ + *rest_out = unescape_string(line, addrport_out, &sz); + if (!*rest_out || (*addrport_out && sz != strlen(*addrport_out))) { + tor_free(*addrport_out); + return -1; + } + *rest_out = eat_whitespace(*rest_out); + return 0; + } else { + // Is there a unix: prefix? + if (!strcmpstart(line, unix_socket_prefix)) { + line += strlen(unix_socket_prefix); + *is_unix_out = 1; + } else { + *is_unix_out = 0; + } - if (strcmpstart(addrport, unix_socket_prefix)) { - /* Not a Unix socket path. */ - return -ENOENT; + const char *end = find_whitespace(line); + if (BUG(!end)) { + end = strchr(line, '\0'); // LCOV_EXCL_LINE -- this can't be NULL + } + tor_assert(end && end >= line); + *addrport_out = tor_strndup(line, end - line); + *rest_out = eat_whitespace(end); + return 0; } - - log_warn(LD_CONFIG, - "Port configuration %s is for an AF_UNIX socket, but we have no" - "support available on this platform", - escaped(addrport)); - return -ENOSYS; } -#endif /* defined(HAVE_SYS_UN_H) */ static void warn_client_dns_cache(const char *option, int disabling) @@ -6515,16 +6525,16 @@ parse_port_config(smartlist_t *out, /* At last we can actually parse the FooPort lines. The syntax is: * [Addr:](Port|auto) [Options].*/ elts = smartlist_new(); + char *addrport = NULL; for (; ports; ports = ports->next) { tor_addr_t addr; - int port, ret; + int port; int sessiongroup = SESSION_GROUP_UNSET; unsigned isolation = ISO_DEFAULT; int prefer_no_auth = 0; int socks_iso_keep_alive = 0; - char *addrport; uint16_t ptmp=0; int ok; /* This must be kept in sync with port_cfg_new's defaults */ @@ -6538,23 +6548,31 @@ parse_port_config(smartlist_t *out, relax_dirmode_check = 0, has_used_unix_socket_only_option = 0; - smartlist_split_string(elts, ports->value, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - if (smartlist_len(elts) == 0) { - log_warn(LD_CONFIG, "Invalid %sPort line with no value", portname); + int is_unix_tagged_addr = 0; + const char *rest_of_line = NULL; + if (port_cfg_line_extract_addrport(ports->value, + &addrport, &is_unix_tagged_addr, &rest_of_line)<0) { + log_warn(LD_CONFIG, "Invalid %sPort line with unparsable address", + portname); + goto err; + } + if (strlen(addrport) == 0) { + log_warn(LD_CONFIG, "Invalid %sPort line with no address", portname); goto err; } - /* Now parse the addr/port value */ - addrport = smartlist_get(elts, 0); + /* Split the remainder... */ + smartlist_split_string(elts, rest_of_line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); /* Let's start to check if it's a Unix socket path. */ - ret = config_parse_unix_port(addrport, &unix_socket_path); - if (ret < 0 && ret != -ENOENT) { - if (ret == -EINVAL) { - log_warn(LD_CONFIG, "Empty Unix socket path."); - } + if (is_unix_tagged_addr) { +#ifndef HAVE_SYS_UN_H + log_warn(LD_CONFIG, "Unix sockets not supported on this system."); goto err; +#endif + unix_socket_path = addrport; + addrport = NULL; } if (unix_socket_path && @@ -6612,9 +6630,6 @@ parse_port_config(smartlist_t *out, if (use_server_options) { /* This is a server port; parse advertising options */ SMARTLIST_FOREACH_BEGIN(elts, char *, elt) { - if (elt_sl_idx == 0) - continue; /* Skip addr:port */ - if (!strcasecmp(elt, "NoAdvertise")) { no_advertise = 1; } else if (!strcasecmp(elt, "NoListen")) { @@ -6662,8 +6677,6 @@ parse_port_config(smartlist_t *out, SMARTLIST_FOREACH_BEGIN(elts, char *, elt) { int no = 0, isoflag = 0; const char *elt_orig = elt; - if (elt_sl_idx == 0) - continue; /* Skip addr:port */ if (!strcasecmpstart(elt, "SessionGroup=")) { int group = (int)tor_parse_long(elt+strlen("SessionGroup="), @@ -6880,6 +6893,7 @@ parse_port_config(smartlist_t *out, } SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); smartlist_clear(elts); + tor_free(addrport); } if (warn_nonlocal && out) { @@ -6903,6 +6917,7 @@ parse_port_config(smartlist_t *out, SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); smartlist_free(elts); tor_free(unix_socket_path); + tor_free(addrport); return retval; } diff --git a/src/or/config.h b/src/or/config.h index 208659acb7..f5a19602f2 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -128,7 +128,11 @@ int addressmap_register_auto(const char *from, const char *to, time_t expires, addressmap_entry_source_t addrmap_source, const char **msg); -int config_parse_unix_port(const char *addrport, char **path_out); + +int port_cfg_line_extract_addrport(const char *line, + char **addrport_out, + int *is_unix_out, + const char **rest_out); /** Represents the information stored in a torrc Bridge line. */ typedef struct bridge_line_t { diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 114a56b74e..a2d7a37378 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -347,22 +347,20 @@ rend_service_parse_port_config(const char *string, const char *sep, int realport = 0; uint16_t p; tor_addr_t addr; - const char *addrport; rend_service_port_config_t *result = NULL; unsigned int is_unix_addr = 0; - char *socket_path = NULL; + const char *socket_path = NULL; char *err_msg = NULL; + char *addrport = NULL; sl = smartlist_new(); smartlist_split_string(sl, string, sep, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) { + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); + if (smartlist_len(sl) < 1 || BUG(smartlist_len(sl) > 2)) { if (err_msg_out) err_msg = tor_strdup("Bad syntax in hidden service port configuration."); - goto err; } - virtport = (int)tor_parse_long(smartlist_get(sl,0), 10, 1, 65535, NULL,NULL); if (!virtport) { if (err_msg_out) @@ -371,7 +369,6 @@ rend_service_parse_port_config(const char *string, const char *sep, goto err; } - if (smartlist_len(sl) == 1) { /* No addr:port part; use default. */ realport = virtport; @@ -379,17 +376,18 @@ rend_service_parse_port_config(const char *string, const char *sep, } else { int ret; - addrport = smartlist_get(sl,1); - ret = config_parse_unix_port(addrport, &socket_path); - if (ret < 0 && ret != -ENOENT) { - if (ret == -EINVAL) - if (err_msg_out) - err_msg = tor_strdup("Empty socket path in hidden service port " - "configuration."); - + const char *addrport_element = smartlist_get(sl,1); + const char *rest = NULL; + int is_unix; + ret = port_cfg_line_extract_addrport(addrport_element, &addrport, + &is_unix, &rest); + if (ret < 0) { + tor_asprintf(&err_msg, "Couldn't process address <%s> from hidden service " + "configuration", addrport_element); goto err; } - if (socket_path) { + if (is_unix) { + socket_path = addrport; is_unix_addr = 1; } else if (strchr(addrport, ':') || strchr(addrport, '.')) { /* else try it as an IP:port pair if it has a : or . in it */ @@ -427,10 +425,10 @@ rend_service_parse_port_config(const char *string, const char *sep, } err: + tor_free(addrport); if (err_msg_out) *err_msg_out = err_msg; SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); - if (socket_path) tor_free(socket_path); return result; } diff --git a/src/test/test_config.c b/src/test/test_config.c index ee1686c65a..4efefa8050 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -3710,6 +3710,145 @@ test_config_default_fallback_dirs(void *arg) clear_dir_servers(); } +static void +test_config_port_cfg_line_extract_addrport(void *arg) +{ + (void)arg; + int unixy = 0; + const char *rest = NULL; + char *a = NULL; + + tt_int_op(port_cfg_line_extract_addrport("", &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("hello", &a, &unixy, &rest), + OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "hello");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(" flipperwalt gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(" flipperwalt \t gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("flipperwalt \t gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:flipperwalt \t gersplut", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "flipperwalt");; + tt_str_op(rest, OP_EQ, "gersplut"); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:lolol ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(" unix:lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("foobar:lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, "foobar:lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport(":lolol", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 0); + tt_str_op(a, OP_EQ, ":lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\"", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\" ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, ""); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lolol\" foo ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lolol");; + tt_str_op(rest, OP_EQ, "foo "); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol ol\" foo ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lol ol");; + tt_str_op(rest, OP_EQ, "foo "); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\\" ol\" foo ", + &a, &unixy, &rest), OP_EQ, 0); + tt_int_op(unixy, OP_EQ, 1); + tt_str_op(a, OP_EQ, "lol\" ol");; + tt_str_op(rest, OP_EQ, "foo "); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\\" ol foo ", + &a, &unixy, &rest), OP_EQ, -1); + tor_free(a); + + tt_int_op(port_cfg_line_extract_addrport("unix:\"lol\\0\" ol foo ", + &a, &unixy, &rest), OP_EQ, -1); + tor_free(a); + + done: + tor_free(a); +} + + static config_line_t * mock_config_line(const char *key, const char *val) { @@ -4050,6 +4189,49 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); #endif + // Test success with quoted unix: address. + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar\" " + "NoDNSRequest NoIPv4Traffic"); + ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS", + CONN_TYPE_AP_LISTENER, NULL, 0, + CL_PORT_TAKES_HOSTNAMES); +#ifdef _WIN32 + tt_int_op(ret, OP_EQ, -1); +#else + tt_int_op(ret, OP_EQ, 0); + tt_int_op(smartlist_len(slout), OP_EQ, 1); + port_cfg = (port_cfg_t *)smartlist_get(slout, 0); + tt_int_op(port_cfg->entry_cfg.dns_request, OP_EQ, 0); + tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 0); + tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 0); + tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); +#endif + + // Test failure with broken quoted unix: address. + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar " + "NoDNSRequest NoIPv4Traffic"); + ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS", + CONN_TYPE_AP_LISTENER, NULL, 0, + CL_PORT_TAKES_HOSTNAMES); + tt_int_op(ret, OP_EQ, -1); + + // Test failure with empty quoted unix: address. + config_free_lines(config_port_valid); config_port_valid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_valid = mock_config_line("SOCKSPort", "unix:\"\" " + "NoDNSRequest NoIPv4Traffic"); + ret = parse_port_config(slout, config_port_valid, NULL, "SOCKS", + CONN_TYPE_AP_LISTENER, NULL, 0, + CL_PORT_TAKES_HOSTNAMES); + tt_int_op(ret, OP_EQ, -1); + // Test success with OnionTrafficOnly (no DNS, no ipv4, no ipv6) config_free_lines(config_port_valid); config_port_valid = NULL; SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); @@ -4690,6 +4872,15 @@ test_config_parse_port_config__ports__server_options(void *data) 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); + // Check for failure with empty unix: address. + config_free_lines(config_port_invalid); config_port_invalid = NULL; + SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); + smartlist_clear(slout); + config_port_invalid = mock_config_line("ORPort", "unix:\"\""); + ret = parse_port_config(slout, config_port_invalid, NULL, "ORPort", 0, NULL, + 0, CL_PORT_SERVER_OPTIONS); + tt_int_op(ret, OP_EQ, -1); + done: if (slout) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); @@ -4719,6 +4910,7 @@ struct testcase_t config_tests[] = { CONFIG_TEST(write_to_data_subdir, TT_FORK), CONFIG_TEST(fix_my_family, 0), CONFIG_TEST(directory_fetch, 0), + CONFIG_TEST(port_cfg_line_extract_addrport, 0), CONFIG_TEST(parse_port_config__listenaddress, 0), CONFIG_TEST(parse_port_config__ports__no_ports_given, 0), CONFIG_TEST(parse_port_config__ports__server_options, 0), diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 0dea8473b9..4ae35c8fe0 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -137,6 +137,8 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("80,[2001:db8::1]:8080", sep, &err_msg); tt_assert(cfg); tt_assert(!err_msg); + rend_service_port_config_free(cfg); + cfg = NULL; /* XXX: Someone should add tests for AF_UNIX targets if supported. */ @@ -151,6 +153,53 @@ test_rend_service_parse_port_config(void *arg) cfg = rend_service_parse_port_config("90001", sep, &err_msg); tt_assert(!cfg); tt_assert(err_msg); + tor_free(err_msg); + + /* unix port */ + cfg = NULL; + + /* quoted unix port */ + tor_free(err_msg); + cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar\"", + " ", &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + rend_service_port_config_free(cfg); + cfg = NULL; + + /* quoted unix port */ + tor_free(err_msg); + cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar\"", + " ", &err_msg); + tt_assert(cfg); + tt_assert(!err_msg); + rend_service_port_config_free(cfg); + cfg = NULL; + + /* quoted unix port, missing end quote */ + cfg = rend_service_parse_port_config("100 unix:\"/tmp/foo bar", + " ", &err_msg); + tt_assert(!cfg); + tt_str_op(err_msg, OP_EQ, "Couldn't process address <unix:\"/tmp/foo bar> " + "from hidden service configuration"); + tor_free(err_msg); + + /* bogus IP address */ + cfg = rend_service_parse_port_config("100 1.2.3.4.5:9000", + " ", &err_msg); + tt_assert(!cfg); + tt_str_op(err_msg, OP_EQ, "Unparseable address in hidden service port " + "configuration."); + tor_free(err_msg); + + /* bogus port port */ + cfg = rend_service_parse_port_config("100 99999", + " ", &err_msg); + tt_assert(!cfg); + tt_str_op(err_msg, OP_EQ, "Unparseable or out-of-range port \"99999\" " + "in hidden service port configuration."); + tor_free(err_msg); + done: rend_service_port_config_free(cfg); |