Add internet address/hostname validators in tr_inet_util.[ch]
authorJennifer Richards <jennifer@painless-security.com>
Wed, 30 May 2018 00:40:26 +0000 (20:40 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Wed, 30 May 2018 00:40:26 +0000 (20:40 -0400)
CMakeLists.txt
common/tr_inet_util.c [new file with mode: 0644]
include/tr_inet_util.h [new file with mode: 0644]

index 52ee9d6..0761bfc 100644 (file)
@@ -96,7 +96,7 @@ set(SOURCE_FILES
     trp/trp_upd.c
     trp/trpc.c
     trp/trps.c include/tr_name_internal.h mon/mon_req.c mon/mon_req_encode.c mon/mon_req_decode.c
-        mon/mon_resp.c mon/mon_common.c mon/mon_resp_encode.c mon/mon_resp_decode.c tr/tr_mon.c mon/mons.c include/tr_socket.h common/tr_gss.c include/tr_gss.h common/tr_config_internal.c mon/mons_handlers.c include/mons_handlers.h tr/tr_tid_mons.c tr/tr_tid_mons.c trp/trp_route.c include/trp_route.h trp/trp_rtable_encoders.c trp/trp_route_encoders.c trp/trp_peer.c include/trp_peer.h trp/trp_peer_encoders.c trp/trp_ptable_encoders.c common/tr_idp_encoders.c common/tr_comm_encoders.c common/tr_rp_client.c include/tr_rp_client.h common/tr_rp_client_encoders.c common/tr_filter_encoders.c common/tr_config_encoders.c common/tr_config_filters.c common/tr_config_realms.c common/tr_config_rp_clients.c common/tr_config_orgs.c common/tr_config_comms.c common/tr_list.c include/tr_list.h include/tr_constraint_internal.h include/tr_json_util.h common/tr_aaa_server.c include/tr_aaa_server.h)
+        mon/mon_resp.c mon/mon_common.c mon/mon_resp_encode.c mon/mon_resp_decode.c tr/tr_mon.c mon/mons.c include/tr_socket.h common/tr_gss.c include/tr_gss.h common/tr_config_internal.c mon/mons_handlers.c include/mons_handlers.h tr/tr_tid_mons.c tr/tr_tid_mons.c trp/trp_route.c include/trp_route.h trp/trp_rtable_encoders.c trp/trp_route_encoders.c trp/trp_peer.c include/trp_peer.h trp/trp_peer_encoders.c trp/trp_ptable_encoders.c common/tr_idp_encoders.c common/tr_comm_encoders.c common/tr_rp_client.c include/tr_rp_client.h common/tr_rp_client_encoders.c common/tr_filter_encoders.c common/tr_config_encoders.c common/tr_config_filters.c common/tr_config_realms.c common/tr_config_rp_clients.c common/tr_config_orgs.c common/tr_config_comms.c common/tr_list.c include/tr_list.h include/tr_constraint_internal.h include/tr_json_util.h common/tr_aaa_server.c include/tr_aaa_server.h common/tr_inet_util.c include/tr_inet_util.h)
 
 # Does not actually build!
 add_executable(trust_router ${SOURCE_FILES})
diff --git a/common/tr_inet_util.c b/common/tr_inet_util.c
new file mode 100644 (file)
index 0000000..65b746f
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <tr_inet_util.h>
+
+/**
+ * Determine whether a string is a valid address of a given family
+ *
+ * @param s string to check
+ * @param af address family (probably AF_INET or AF_INET6)
+ * @return 1 if string is a valid address in the given family, 0 if not, -1 on error (errno set)
+ */
+static int is_valid_address(int af, const char *s)
+{
+  unsigned char buf[sizeof(struct in6_addr)];
+
+  if (s == NULL)
+    return 0;
+  return inet_pton(af, s, buf);
+}
+
+/**
+ * Determine whether a string is a valid IPv4 address
+ * @param s string to validate
+ * @return 1 if a valid reference, 0 otherwise
+ */
+int is_valid_ipv4_address(const char *s)
+{
+  return is_valid_address(AF_INET, s);
+}
+
+/**
+ * Determine whether a string is a valid IPv6 address reference
+ *
+ * I.e., an IPv6 address in brackets
+ *
+ * @param s string to validate
+ * @return 1 if a valid reference, 0 otherwise
+ */
+int is_valid_ipv6_reference(const char *s)
+{
+  char *cpy;
+  size_t len;
+  int valid_ipv6;
+
+  /* check that it starts with an open bracket */
+  if (*s != '[')
+    return 0;
+
+  /* check that it ends with a close bracket */
+  len = strlen(s);
+  if (*(s+len-1) != ']')
+    return 0;
+
+  /* make a null-terminated copy of the string omitting the brackets */
+  cpy = strndup(s+1, len-2);
+  if (cpy == NULL)
+    return -1;
+
+  valid_ipv6 = is_valid_address(AF_INET6, cpy);
+  free(cpy);
+
+  return valid_ipv6;
+}
+
+static int is_valid_dns_char(char c)
+{
+  /* digits ok */
+  if ( ('0' <= c) && ('9' >= c))
+    return 1;
+
+  /* letters ok */
+  if ( (('a' <= c) && ('z' >= c))
+       || (('A' <= c) && ('Z' >= c)) )
+    return 1;
+
+  /* '-' ok */
+  if ('-' == c)
+    return 1;
+
+  /* everything else illegal */
+  return 0;
+}
+
+/**
+ * Helper to validate a DNS label
+ *
+ * Checks whether the string starting at s[start] and ending at s[end-1]
+ * is a valid DNS label.
+ *
+ * Does not check the length of the label.
+ *
+ * @param s
+ * @param start
+ * @param end
+ * @return
+ */
+static int is_valid_dns_label(const char *s, size_t start, size_t end)
+{
+  size_t ii;
+
+  /* Check that there is at least one character.
+   * Be careful - size_t is unsigned */
+  if (start >= end)
+    return 0;
+
+  /* must neither start nor end with '-' */
+  if ((s[start] == '-')
+      || s[end-1] == '-')
+    return 0;
+
+  /* make sure all characters are valid */
+  for (ii=start; ii<end; ii++) {
+    if (! is_valid_dns_char(s[ii]))
+      return 0;
+  }
+
+  return 1;
+}
+
+/**
+ * Determine whether a string is a valid DNS name
+ *
+ * Does not check the length of the name or of the indivdiual
+ * labels in it.
+ *
+ * @param s string to validate
+ * @return 1 if a valid DNS name, 0 otherwise
+ */
+int is_valid_dns_name(const char *s)
+{
+  size_t label_start;
+  size_t label_end;
+
+  /* reject some trivial cases */
+  if ((s == NULL)
+      || (*s == '\0'))
+    return 0;
+
+  /* Walk along with the end counter until we encounter a '.'. When that
+   * happens, we have a complete DNS label. Validate that, then set the start
+   * counter to one character past the end pointer, which will either be the
+   * next character in the DNS name or the null terminator. Since we stop as
+   * soon as the end counter reaches a null character, this will never refer
+   * to an invalid address. */
+  for (label_start = 0, label_end = 0;
+       s[label_end] != '\0';
+       label_end++) {
+    if (s[label_end] == '.') {
+      if (! is_valid_dns_label(s, label_start, label_end))
+        return 0;
+
+      label_start = label_end+1;
+    }
+  }
+
+  if (s[label_start] == '\0')
+    return 1; /* we must have ended on a '.' */
+
+  /* There was one more label to validate */
+  return is_valid_dns_label(s, label_start, label_end);
+}
+
+/**
+ * Validate a host string
+ *
+ * Valid formats:
+ *   IPv4 address (dotted quad)
+ *   IPv6 address in brackets (e.g., [::1])
+ *   DNS hostname (labels made of alphanumerics or "-", separated by dots)
+ *
+ * @param s string to validate
+ * @return 1 if a valid host specification, 0 otherwise
+ */
+int is_valid_host(const char *s)
+{
+  if (is_valid_ipv4_address(s))
+    return 1;
+
+  if (is_valid_ipv6_reference(s))
+    return 1;
+
+  if (is_valid_dns_name(s))
+    return 1;
+
+  return 0;
+}
diff --git a/include/tr_inet_util.h b/include/tr_inet_util.h
new file mode 100644 (file)
index 0000000..348332a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TRUST_ROUTER_TR_INET_UTIL_H
+#define TRUST_ROUTER_TR_INET_UTIL_H
+
+#include <arpa/inet.h>
+
+int is_valid_ipv4_address(const char *s);
+int is_valid_ipv6_reference(const char *s);
+int is_valid_dns_name(const char *s);
+int is_valid_host(const char *s);
+
+#endif //TRUST_ROUTER_TR_INET_UTIL_H