aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-06-27 15:45:53 -0400
committerNick Mathewson <nickm@torproject.org>2018-06-27 16:18:42 -0400
commit3cff3e825a1478fc3350bbca16f091b8f635f921 (patch)
tree035981c06b58324dea01a8816332274be6381c4c /src/lib
parente165c9c304800718daa589469349282110e00909 (diff)
downloadtor-3cff3e825a1478fc3350bbca16f091b8f635f921.tar.gz
tor-3cff3e825a1478fc3350bbca16f091b8f635f921.zip
Move several address-string-testing functions to address.c
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/net/address.c115
-rw-r--r--src/lib/net/address.h5
2 files changed, 120 insertions, 0 deletions
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 69abb98a1e..10e38871ee 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -2139,3 +2139,118 @@ tor_addr_port_eq(const tor_addr_port_t *a,
{
return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
}
+
+/** Return true if <b>string</b> represents a valid IPv4 adddress in
+ * 'a.b.c.d' form.
+ */
+int
+string_is_valid_ipv4_address(const char *string)
+{
+ struct in_addr addr;
+
+ return (tor_inet_pton(AF_INET,string,&addr) == 1);
+}
+
+/** Return true if <b>string</b> represents a valid IPv6 address in
+ * a form that inet_pton() can parse.
+ */
+int
+string_is_valid_ipv6_address(const char *string)
+{
+ struct in6_addr addr;
+
+ return (tor_inet_pton(AF_INET6,string,&addr) == 1);
+}
+
+/** Return true iff <b>string</b> is a valid destination address,
+ * i.e. either a DNS hostname or IPv4/IPv6 address string.
+ */
+int
+string_is_valid_dest(const char *string)
+{
+ char *tmp = NULL;
+ int retval;
+ size_t len;
+
+ if (string == NULL)
+ return 0;
+
+ len = strlen(string);
+
+ if (len == 0)
+ return 0;
+
+ if (string[0] == '[' && string[len - 1] == ']')
+ string = tmp = tor_strndup(string + 1, len - 2);
+
+ retval = string_is_valid_ipv4_address(string) ||
+ string_is_valid_ipv6_address(string) ||
+ string_is_valid_nonrfc_hostname(string);
+
+ tor_free(tmp);
+
+ return retval;
+}
+
+/** Return true iff <b>string</b> matches a pattern of DNS names
+ * that we allow Tor clients to connect to.
+ *
+ * Note: This allows certain technically invalid characters ('_') to cope
+ * with misconfigured zones that have been encountered in the wild.
+ */
+int
+string_is_valid_nonrfc_hostname(const char *string)
+{
+ int result = 1;
+ int has_trailing_dot;
+ char *last_label;
+ smartlist_t *components;
+
+ if (!string || strlen(string) == 0)
+ return 0;
+
+ if (string_is_valid_ipv4_address(string))
+ return 0;
+
+ components = smartlist_new();
+
+ smartlist_split_string(components,string,".",0,0);
+
+ if (BUG(smartlist_len(components) == 0))
+ return 0; // LCOV_EXCL_LINE should be impossible given the earlier checks.
+
+ /* Allow a single terminating '.' used rarely to indicate domains
+ * are FQDNs rather than relative. */
+ last_label = (char *)smartlist_get(components,
+ smartlist_len(components) - 1);
+ has_trailing_dot = (last_label[0] == '\0');
+ if (has_trailing_dot) {
+ smartlist_pop_last(components);
+ tor_free(last_label);
+ last_label = NULL;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(components, char *, c) {
+ if ((c[0] == '-') || (*c == '_')) {
+ result = 0;
+ break;
+ }
+
+ do {
+ result = (TOR_ISALNUM(*c) || (*c == '-') || (*c == '_'));
+ c++;
+ } while (result && *c);
+
+ if (result == 0) {
+ break;
+ }
+ } SMARTLIST_FOREACH_END(c);
+
+ SMARTLIST_FOREACH_BEGIN(components, char *, c) {
+ tor_free(c);
+ } SMARTLIST_FOREACH_END(c);
+
+ smartlist_free(components);
+
+ return result;
+}
diff --git a/src/lib/net/address.h b/src/lib/net/address.h
index 78b7987556..f8ea573c30 100644
--- a/src/lib/net/address.h
+++ b/src/lib/net/address.h
@@ -357,6 +357,11 @@ tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
int tor_addr_port_eq(const tor_addr_port_t *a,
const tor_addr_port_t *b);
+int string_is_valid_dest(const char *string);
+int string_is_valid_nonrfc_hostname(const char *string);
+int string_is_valid_ipv4_address(const char *string);
+int string_is_valid_ipv6_address(const char *string);
+
#ifdef ADDRESS_PRIVATE
MOCK_DECL(struct smartlist_t *,get_interface_addresses_raw,(int severity,
sa_family_t family));