Filter rDNS returns for bad chars
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 9 Aug 2022 09:57:56 +0000 (10:57 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 9 Aug 2022 09:57:56 +0000 (10:57 +0100)
doc/doc-txt/ChangeLog
src/src/globals.c
src/src/globals.h
src/src/host.c

index b813033c1ae914ca54f82b4381b45cc45b952112..d17370589aa588813f3839b99407f63a8b2d89c4 100644 (file)
@@ -23,6 +23,9 @@ JH/05 Follow symlinks for placing a watch on TLS creds files.  This means
       it would be the dir with the first symlink.  We still do not monitor
       the entire path.
 
       it would be the dir with the first symlink.  We still do not monitor
       the entire path.
 
+JH/06 Check for bad chars in rDNS for sender_host_name. The OpenBSD (at least)
+      dn_expand() is happy to pass them through.
+
 
 Exim version 4.96
 -----------------
 
 Exim version 4.96
 -----------------
index c95d24b4743aadf90a3aa01497ce9870497ced5a..574ee60a4819330614fd15f87ba9035aaa0e2a35 100644 (file)
@@ -1016,6 +1016,10 @@ uschar *keep_environment       = NULL;
 int     keep_malformed         = 4*24*60*60;    /* 4 days */
 
 uschar *eldap_dn               = NULL;
 int     keep_malformed         = 4*24*60*60;    /* 4 days */
 
 uschar *eldap_dn               = NULL;
+const uschar *letter_digit_hyphen_dot =
+    US"abcdefghijklmnopqrstuvwxyz"
+      ".-0123456789"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 #ifdef EXPERIMENTAL_ESMTP_LIMITS
 uschar *limits_advertise_hosts = US"*";
 #endif
 #ifdef EXPERIMENTAL_ESMTP_LIMITS
 uschar *limits_advertise_hosts = US"*";
 #endif
index c9ef5e484ff045b5ebbaece100fa0c697d3a53de..3f3c798b71b5a40d5fd1258e62667b6876abb13e 100644 (file)
@@ -680,6 +680,7 @@ extern uschar *keep_environment;       /* Whitelist for environment variables */
 extern int     keep_malformed;         /* Time to keep malformed messages */
 
 extern uschar *eldap_dn;               /* Where LDAP DNs are left */
 extern int     keep_malformed;         /* Time to keep malformed messages */
 
 extern uschar *eldap_dn;               /* Where LDAP DNs are left */
+extern const uschar *letter_digit_hyphen_dot; /* Legitimate DNS host name chars */
 #ifdef EXPERIMENTAL_ESMTP_LIMITS
 extern uschar *limits_advertise_hosts; /* for banner/EHLO pipelining */
 #endif
 #ifdef EXPERIMENTAL_ESMTP_LIMITS
 extern uschar *limits_advertise_hosts; /* for banner/EHLO pipelining */
 #endif
index fed9f4b5f241d24626996fa95b0fd5d9f798358e..b6c2ea0827053c3e8a2daedbd249200e042d94d0 100644 (file)
@@ -84,13 +84,13 @@ random_number(int limit)
 if (limit < 1)
   return 0;
 if (random_seed == 0)
 if (limit < 1)
   return 0;
 if (random_seed == 0)
-  {
-  if (f.running_in_test_harness) random_seed = 42; else
+  if (f.running_in_test_harness)
+    random_seed = 42;
+  else
     {
     int p = (int)getpid();
     random_seed = (int)time(NULL) ^ ((p << 16) | p);
     }
     {
     int p = (int)getpid();
     random_seed = (int)time(NULL) ^ ((p << 16) | p);
     }
-  }
 random_seed = 1103515245 * random_seed + 12345;
 return (unsigned int)(random_seed >> 16) % limit;
 }
 random_seed = 1103515245 * random_seed + 12345;
 return (unsigned int)(random_seed >> 16) % limit;
 }
@@ -1646,6 +1646,7 @@ while ((ordername = string_nextinlist(&list, &sep, NULL, 0)))
            rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == T_PTR)
         {
         uschar * s = store_get(ssize, GET_TAINTED);    /* names are tainted */
            rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == T_PTR)
         {
         uschar * s = store_get(ssize, GET_TAINTED);    /* names are tainted */
+       unsigned slen;
 
         /* If an overlong response was received, the data will have been
         truncated and dn_expand may fail. */
 
         /* If an overlong response was received, the data will have been
         truncated and dn_expand may fail. */
@@ -1658,13 +1659,19 @@ while ((ordername = string_nextinlist(&list, &sep, NULL, 0)))
           break;
           }
 
           break;
           }
 
-        store_release_above(s + Ustrlen(s) + 1);
-        if (!s[0])
+        store_release_above(s + (slen = Ustrlen(s)) + 1);
+        if (!*s)
           {
           HDEBUG(D_host_lookup) debug_printf("IP address lookup yielded an "
             "empty name: treated as non-existent host name\n");
           continue;
           }
           {
           HDEBUG(D_host_lookup) debug_printf("IP address lookup yielded an "
             "empty name: treated as non-existent host name\n");
           continue;
           }
+       if (Ustrspn(s, letter_digit_hyphen_dot) != slen)
+          {
+          HDEBUG(D_host_lookup) debug_printf("IP address lookup yielded an "
+            "illegal name (bad char): treated as non-existent host name\n");
+          continue;
+          }
         if (!sender_host_name) sender_host_name = s;
        else *aptr++ = s;
         while (*s) { *s = tolower(*s); s++; }
         if (!sender_host_name) sender_host_name = s;
        else *aptr++ = s;
         while (*s) { *s = tolower(*s); s++; }