diff --git a/src/common/util.c b/src/common/util.c
index 90204befc0..1818b4f19e 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1071,6 +1071,17 @@ string_is_valid_ipv6_address(const char *string)
return (tor_inet_pton(AF_INET6,string,&addr) == 1);
}
+/** Return true iff string is a valid destination address,
+ * i.e. either a DNS hostname or IPv4/IPv6 address string.
+ */
+int
+string_is_valid_dest(const char *string)
+{
+ return string_is_valid_ipv4_address(string) ||
+ string_is_valid_ipv6_address(string) ||
+ string_is_valid_hostname(string);
+}
+
/** Return true iff string matches a pattern of DNS names
* that we allow Tor clients to connect to.
*
diff --git a/src/common/util.h b/src/common/util.h
index 2ee0ea28cd..d6bda80363 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -233,6 +233,7 @@ const char *find_str_at_start_of_line(const char *haystack,
const char *needle);
int string_is_C_identifier(const char *string);
int string_is_key_value(int severity, const char *string);
+int string_is_valid_dest(const char *string);
int string_is_valid_hostname(const char *string);
int string_is_valid_ipv4_address(const char *string);
int string_is_valid_ipv6_address(const char *string);
diff --git a/src/or/proto_socks.c b/src/or/proto_socks.c
index 91633d02af..8700fe1269 100644
--- a/src/or/proto_socks.c
+++ b/src/or/proto_socks.c
@@ -393,7 +393,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
req->port = ntohs(get_uint16(data+5+len));
*drain_out = 5+len+2;
- if (!string_is_valid_hostname(req->address)) {
+ if (!string_is_valid_dest(req->address)) {
socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
log_warn(LD_PROTOCOL,
@@ -518,7 +518,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
log_debug(LD_APP,"socks4: Everything is here. Success.");
strlcpy(req->address, startaddr ? startaddr : tmpbuf,
sizeof(req->address));
- if (!string_is_valid_hostname(req->address)) {
+ if (!string_is_valid_dest(req->address)) {
log_warn(LD_PROTOCOL,
"Your application (using socks4 to port %d) gave Tor "
"a malformed hostname: %s. Rejecting the connection.",
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 9ae7530e22..70509e43e7 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -347,17 +347,18 @@ test_socks_5_supported_commands(void *ptr)
socks_request_clear(socks);
- /* SOCKS 5 should NOT reject RESOLVE [F0] reject for IPv6 address
+ /* SOCKS 5 should NOT reject RESOLVE [F0] request for IPv6 address
* string if SafeSocks is enabled. */
ADD_DATA(buf, "\x05\x01\x00");
- ADD_DATA(buf, "\x05\xF0\x00\x03\x27");
- ADD_DATA(buf, "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
+ ADD_DATA(buf, "\x05\xF0\x00\x03\x29");
+ ADD_DATA(buf, "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]");
ADD_DATA(buf, "\x01\x02");
tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, 1),
OP_EQ, -1);
- tt_str_op("2001:0db8:85a3:0000:0000:8a2e:0370:7334", OP_EQ, socks->address);
+ tt_str_op("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", OP_EQ,
+ socks->address);
tt_int_op(258, OP_EQ, socks->port);
tt_int_op(0, OP_EQ, buf_datalen(buf));