diff --git a/src/common/address.c b/src/common/address.c index a714ead5e6..fff3206a0d 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -1393,7 +1393,46 @@ is_internal_IP(uint32_t ip, int for_listening) return tor_addr_is_internal(&myaddr, for_listening); } -/** Given an address of the form "host:port", try to divide it into its host +/** Given an address of the form "ip:port", try to divide it into its + * ip and port portions, setting *address_out to a newly + * allocated string holding the address portion and *port_out + * to the port. + * + * Don't do DNS lookups and don't allow domain names in the field. + * Don't accept addrport of the form "" or ":0". + * + * Return 0 on success, -1 on failure. */ +int +tor_addr_port_parse(int severity, const char *addrport, + tor_addr_t *address_out, uint16_t *port_out) +{ + int retval = -1; + int r; + char *addr_tmp = NULL; + + tor_assert(addrport); + tor_assert(address_out); + tor_assert(port_out); + + r = tor_addr_port_split(severity, addrport, &addr_tmp, port_out); + if (r < 0) + goto done; + + if (!*port_out) + goto done; + + /* make sure that address_out is an IP address */ + if (tor_addr_parse(address_out, addr_tmp) < 0) + goto done; + + retval = 0; + + done: + tor_free(addr_tmp); + return retval; +} + +/** Given an address of the form "host[:port]", try to divide it into its host * ane port portions, setting *address_out to a newly allocated string * holding the address portion and *port_out to the port (or 0 if no * port is given). Return 0 on success, -1 on failure. */ diff --git a/src/common/address.h b/src/common/address.h index 067b7a0ca6..61c6eb80ee 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -206,6 +206,9 @@ int tor_addr_is_loopback(const tor_addr_t *addr); int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out); +int tor_addr_port_parse(int severity, const char *addrport, + tor_addr_t *address_out, uint16_t *port_out); + int tor_addr_hostname_is_local(const char *name); /* IPv4 helpers */ diff --git a/src/or/config.c b/src/or/config.c index 822bc629bc..48e33b9c80 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4152,7 +4152,7 @@ get_bindaddr_from_transport_listen_line(const char *line,const char *transport) smartlist_t *items = NULL; const char *parsed_transport = NULL; char *addrport = NULL; - char *addr = NULL; + tor_addr_t addr; uint16_t port = 0; items = smartlist_new(); @@ -4172,18 +4172,12 @@ get_bindaddr_from_transport_listen_line(const char *line,const char *transport) goto err; /* Validate addrport */ - if (tor_addr_port_split(LOG_WARN, addrport, &addr, &port)<0) { + if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port)<0) { log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr " "address '%s'", addrport); goto err; } - if (!port) { - log_warn(LD_CONFIG, - "ServerTransportListenAddr address '%s' has no port.", addrport); - goto err; - } - goto done; err: @@ -4193,7 +4187,6 @@ get_bindaddr_from_transport_listen_line(const char *line,const char *transport) done: SMARTLIST_FOREACH(items, char*, s, tor_free(s)); smartlist_free(items); - tor_free(addr); return addrport; } diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 0dcc0174a8..065ca58fe3 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -623,12 +623,65 @@ test_addr_ip6_helpers(void) ; } +/** Test tor_addr_port_parse(). */ +static void +test_addr_parse(void) +{ + int r; + tor_addr_t addr; + char buf[TOR_ADDR_BUF_LEN]; + uint16_t port = 0; + + /* Correct call. */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2.1:1234", + &addr, &port); + test_assert(r == 0); + tor_addr_to_str(buf, &addr, sizeof(buf), 0); + test_streq(buf, "192.0.2.1"); + test_eq(port, 1234); + + /* Domain name. */ + r= tor_addr_port_parse(LOG_DEBUG, + "torproject.org:1234", + &addr, &port); + test_assert(r == -1); + + /* Only IP. */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2.2", + &addr, &port); + test_assert(r == -1); + + /* Bad port. */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2.2:66666", + &addr, &port); + test_assert(r == -1); + + /* Only domain name */ + r= tor_addr_port_parse(LOG_DEBUG, + "torproject.org", + &addr, &port); + test_assert(r == -1); + + /* Bad IP address */ + r= tor_addr_port_parse(LOG_DEBUG, + "192.0.2:1234", + &addr, &port); + test_assert(r == -1); + + done: + ; +} + #define ADDR_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_addr_ ## name } struct testcase_t addr_tests[] = { ADDR_LEGACY(basic), ADDR_LEGACY(ip6_helpers), + ADDR_LEGACY(parse), END_OF_TESTCASES };