[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Allow a unix: address to contain a C-style quoted string.
commit 05aed5b635fa7148fe2a4ea87e7296fa6bec3087
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Mon Oct 3 16:32:00 2016 -0400
Allow a unix: address to contain a C-style quoted string.
Feature 18753 -- all this to allow spaces.
---
changes/feature18753 | 6 ++
doc/tor.1.txt | 9 ++-
src/common/util.c | 2 +-
src/common/util.h | 1 +
src/or/config.c | 137 ++++++++++++++++++--------------
src/or/config.h | 6 +-
src/or/rendservice.c | 32 ++++----
src/test/test_config.c | 192 +++++++++++++++++++++++++++++++++++++++++++++
src/test/test_controller.c | 49 ++++++++++++
9 files changed, 352 insertions(+), 82 deletions(-)
diff --git a/changes/feature18753 b/changes/feature18753
new file mode 100644
index 0000000..2eb0e35
--- /dev/null
+++ b/changes/feature18753
@@ -0,0 +1,6 @@
+ o Minor features (unix domain sockets):
+ - When configuring a unix domain socket for a SocksPort,
+ ControlPort, or Hidden service, you can now wrap the address
+ in quotes, using C-style escapes inside the quotes. This
+ allows unix domain socket paths to contain spaces.
+
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 9f4eb31..1a584e8 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -323,6 +323,8 @@ GENERAL OPTIONS
any process on the local host to control it. (Setting both authentication
methods means either method is sufficient to authenticate to Tor.) This
option is required for many Tor controllers; most use the value of 9051.
+ If a unix domain socket is used, you may quote the path using standard
+ C escape sequences.
Set it to "auto" to have Tor pick a port for you. (Default: 0) +
+
Recognized flags are...
@@ -1032,7 +1034,9 @@ The following options are useful only for clients (that is, if
applications. Set this to 0 if you don't want to allow application
connections via SOCKS. Set it to "auto" to have Tor pick a port for
you. This directive can be specified multiple times to bind
- to multiple addresses/ports. (Default: 9050) +
+ to multiple addresses/ports. If a unix domain socket is used, you may
+ quote the path using standard C escape sequences.
+ (Default: 9050) +
+
NOTE: Although this option allows you to specify an IP address
other than localhost, you should do so only with extreme caution.
@@ -2342,7 +2346,8 @@ The following options are used to configure a hidden service.
recent HiddenServiceDir. By default, this option maps the virtual port to
the same port on 127.0.0.1 over TCP. You may override the target port,
address, or both by specifying a target of addr, port, addr:port, or
- **unix:**__path__. (You can specify an IPv6 target as [addr]:port.)
+ **unix:**__path__. (You can specify an IPv6 target as [addr]:port. Unix
+ paths may be quoted, and may use standard C escapes.)
You may also have multiple lines with the same VIRTPORT: when a user
connects to that VIRTPORT, one of the TARGETs from those lines will be
chosen at random.
diff --git a/src/common/util.c b/src/common/util.c
index 259ff87..c632ee4 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 57605cc..479fc8d 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 18cbe34..ff43486 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 208659a..f5a1960 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 114a56b..a2d7a37 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 ee1686c..4efefa8 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 0dea847..4ae35c8 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);
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits