TLS: use RFC 6125 rules for certifucate name checks when CNAMES are present. Bug...
[exim.git] / src / src / host.c
index aa142eb9b4ef2997035f8d0e2c1beeea7682a997..99bbba7a3e0f7ee205ba94251563c0faf68d31ed 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or
@@ -182,19 +183,18 @@ dns_scan dnss;
 
 DEBUG(D_host_lookup)
   debug_printf("using host_fake_gethostbyname for %s (%s)\n", name,
-    (af == AF_INET)? "IPv4" : "IPv6");
+    af == AF_INET ? "IPv4" : "IPv6");
 
 /* Handle unqualified "localhost" */
 
 if (Ustrcmp(name, "localhost") == 0)
-  lname = (af == AF_INET)? US"127.0.0.1" : US"::1";
+  lname = af == AF_INET ? US"127.0.0.1" : US"::1";
 
 /* Handle a literal IP address */
 
 if ((ipa = string_is_ip_address(lname, NULL)) != 0)
-  {
-  if ((ipa == 4 && af == AF_INET) ||
-      (ipa == 6 && af == AF_INET6))
+  if (   ipa == 4 && af == AF_INET
+     ||  ipa == 6 && af == AF_INET6)
     {
     int x[4];
     yield = store_get(sizeof(struct hostent), FALSE);
@@ -224,13 +224,12 @@ if ((ipa = string_is_ip_address(lname, NULL)) != 0)
     *error_num = HOST_NOT_FOUND;
     return NULL;
     }
-  }
 
 /* Handle a host name */
 
 else
   {
-  int type = (af == AF_INET)? T_A:T_AAAA;
+  int type = af == AF_INET ? T_A:T_AAAA;
   int rc = dns_lookup_timerwrap(dnsa, lname, type, NULL);
   int count = 0;
 
@@ -729,6 +728,7 @@ host_build_ifacelist(const uschar *list, uschar *name)
 int sep = 0;
 uschar *s;
 ip_address_item * yield = NULL, * last = NULL, * next;
+BOOL taint = is_tainted(list);
 
 while ((s = string_nextinlist(&list, &sep, NULL, 0)))
   {
@@ -747,7 +747,7 @@ while ((s = string_nextinlist(&list, &sep, NULL, 0)))
   address above. The field in the ip_address_item is large enough to hold an
   IPv6 address. */
 
-  next = store_get(sizeof(ip_address_item), FALSE);
+  next = store_get(sizeof(ip_address_item), taint);
   next->next = NULL;
   Ustrcpy(next->address, s);
   next->port = port;
@@ -1646,7 +1646,6 @@ int old_pool, rc;
 int sep = 0;
 uschar *save_hostname;
 uschar **aliases;
-uschar buffer[256];
 uschar *ordername;
 const uschar *list = host_lookup_order;
 dns_answer * dnsa = store_get_dns_answer();
@@ -1672,13 +1671,14 @@ if (f.running_in_test_harness &&
 /* Do lookups directly in the DNS or via gethostbyaddr() (or equivalent), in
 the order specified by the host_lookup_order option. */
 
-while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+while ((ordername = string_nextinlist(&list, &sep, NULL, 0)))
   {
   if (strcmpic(ordername, US"bydns") == 0)
     {
+    uschar * name = dns_build_reverse(sender_host_address);
+
     dns_init(FALSE, FALSE, FALSE);    /* dnssec ctrl by dns_dnssec_ok glbl */
-    dns_build_reverse(sender_host_address, buffer);
-    rc = dns_lookup_timerwrap(dnsa, buffer, T_PTR, NULL);
+    rc = dns_lookup_timerwrap(dnsa, name, T_PTR, NULL);
 
     /* The first record we come across is used for the name; others are
     considered to be aliases. We have to scan twice, in order to find out the
@@ -1950,6 +1950,13 @@ BOOL temp_error = FALSE;
 int af;
 #endif
 
+#ifndef DISABLE_TLS
+/* Copy the host name at this point to the value which is used for
+TLS certificate name checking, before anything modifies it.  */
+
+host->certname = host->name;
+#endif
+
 /* Make sure DNS options are set as required. This appears to be necessary in
 some circumstances when the get..byname() function actually calls the DNS. */
 
@@ -2034,7 +2041,7 @@ for (int i = 1; i <= times;
       && (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log)
     log_long_lookup(US"gethostbyname", host->name, time_msec);
 
-  if (hostdata == NULL)
+  if (!hostdata)
     {
     uschar *error;
     switch (error_num)
@@ -2043,18 +2050,19 @@ for (int i = 1; i <= times;
       case TRY_AGAIN:      error = US"TRY_AGAIN"; break;
       case NO_RECOVERY:    error = US"NO_RECOVERY"; break;
       case NO_DATA:        error = US"NO_DATA"; break;
-      #if NO_DATA != NO_ADDRESS
+    #if NO_DATA != NO_ADDRESS
       case NO_ADDRESS:     error = US"NO_ADDRESS"; break;
-      #endif
+    #endif
       default: error = US"?"; break;
       }
 
     DEBUG(D_host_lookup) debug_printf("%s returned %d (%s)\n",
+      f.running_in_test_harness ? "host_fake_gethostbyname" :
       #if HAVE_IPV6
         #if HAVE_GETIPNODEBYNAME
-        (af == AF_INET6)? "getipnodebyname(af=inet6)" : "getipnodebyname(af=inet)",
+        af == AF_INET6 ? "getipnodebyname(af=inet6)" : "getipnodebyname(af=inet)",
         #else
-        (af == AF_INET6)? "gethostbyname2(af=inet6)" : "gethostbyname2(af=inet)",
+        af == AF_INET6 ? "gethostbyname2(af=inet6)" : "gethostbyname2(af=inet)",
         #endif
       #else
       "gethostbyname",
@@ -2116,6 +2124,9 @@ for (int i = 1; i <= times;
       {
       host_item *next = store_get(sizeof(host_item), FALSE);
       next->name = host->name;
+#ifndef DISABLE_TLS
+      next->certname = host->certname;
+#endif
       next->mx = host->mx;
       next->address = text_address;
       next->port = PORT_NONE;
@@ -2134,12 +2145,12 @@ for (int i = 1; i <= times;
 NULL. If temp_error is set, at least one of the lookups gave a temporary error,
 so we pass that back. */
 
-if (host->address == NULL)
+if (!host->address)
   {
   uschar *msg =
     #ifndef STAND_ALONE
-    (message_id[0] == 0 && smtp_in != NULL)?
-      string_sprintf("no IP address found for host %s (during %s)", host->name,
+    message_id[0] == 0 && smtp_in
+      string_sprintf("no IP address found for host %s (during %s)", host->name,
           smtp_get_connection_info()) :
     #endif
     string_sprintf("no IP address found for host %s", host->name);
@@ -2259,6 +2270,13 @@ BOOL v6_find_again = FALSE;
 BOOL dnssec_fail = FALSE;
 int i;
 
+#ifndef DISABLE_TLS
+/* Copy the host name at this point to the value which is used for
+TLS certificate name checking, before any CNAME-following modifies it.  */
+
+host->certname = host->name;
+#endif
+
 /* If allow_ip is set, a name which is an IP address returns that value
 as its address. This is used for MX records when allow_mx_to_ip is set, for
 those sites that feel they have to flaunt the RFC rules. */