Make verify=helo do the verification on the fly it if was not done
[exim.git] / src / src / smtp_in.c
index 6e62b99e0fb1ce237cc6237058ea9e8f69aa768f..9a736a4b7bb68af059af192b7a0beaffd1283905 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.17 2005/04/27 13:29:32 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.22 2005/08/02 15:19:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -809,7 +809,7 @@ message_size = -1;
 acl_warn_headers = NULL;
 queue_only_policy = FALSE;
 deliver_freeze = FALSE;                              /* Can be set by ACL */
-fake_reject = FALSE;                                 /* Can be set by ACL */
+fake_response = OK;                                  /* Can be set by ACL */
 #ifdef WITH_CONTENT_SCAN
 no_mbox_unspool = FALSE;                             /* Can be set by ACL */
 #endif
@@ -838,6 +838,10 @@ spf_smtp_comment = NULL;
 #endif
 body_linecount = body_zerocount = 0;
 
+sender_rate = sender_rate_limit = sender_rate_period = NULL;
+ratelimiters_mail = NULL;           /* Updated by ratelimit ACL condition */
+                   /* Note that ratelimiters_conn persists across resets. */
+
 for (i = 0; i < ACL_M_MAX; i++) acl_var[ACL_C_MAX + i] = NULL;
 
 /* The message body variables use malloc store. They may be set if this is
@@ -1621,7 +1625,7 @@ if (smtp_enforce_sync && sender_host_address != NULL && !sender_host_notsocket)
       {
       if (rc > 150) rc = 150;
       smtp_inbuffer[rc] = 0;
-      log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: "
+      log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol "
         "synchronization error (input sent without waiting for greeting): "
         "rejected connection from %s input=\"%s\"", host_and_ident(TRUE),
         string_printing(smtp_inbuffer));
@@ -1928,6 +1932,130 @@ return 2;
 
 
 
+/*************************************************
+*             Verify HELO argument               *
+*************************************************/
+
+/* This function is called if helo_verify_hosts or helo_try_verify_hosts is
+matched. It is also called from ACL processing if verify = helo is used and
+verification was not previously tried (i.e. helo_try_verify_hosts was not
+matched). The result of its processing is to set helo_verified and
+helo_verify_failed. These variables should both be FALSE for this function to
+be called.
+
+Note that EHLO/HELO is legitimately allowed to quote an address literal. Allow
+for IPv6 ::ffff: literals.
+
+Argument:   none
+Returns:    TRUE if testing was completed;
+            FALSE on a temporary failure
+*/
+
+BOOL
+smtp_verify_helo(void)
+{
+BOOL yield = TRUE;
+
+HDEBUG(D_receive) debug_printf("verifying EHLO/HELO argument \"%s\"\n",
+  sender_helo_name);
+
+if (sender_helo_name == NULL)
+  {
+  HDEBUG(D_receive) debug_printf("no EHLO/HELO command was issued\n");
+  }
+
+else if (sender_helo_name[0] == '[')
+  {
+  helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address,
+    Ustrlen(sender_host_address)) == 0;
+
+  #if HAVE_IPV6
+  if (!helo_verified)
+    {
+    if (strncmpic(sender_host_address, US"::ffff:", 7) == 0)
+      helo_verified = Ustrncmp(sender_helo_name + 1,
+        sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0;
+    }
+  #endif
+
+  HDEBUG(D_receive)
+    { if (helo_verified) debug_printf("matched host address\n"); }
+  }
+
+/* Do a reverse lookup if one hasn't already given a positive or negative
+response. If that fails, or the name doesn't match, try checking with a forward
+lookup. */
+
+else
+  {
+  if (sender_host_name == NULL && !host_lookup_failed)
+    yield = host_name_lookup() != DEFER;
+
+  /* If a host name is known, check it and all its aliases. */
+
+  if (sender_host_name != NULL)
+    {
+    helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0;
+
+    if (helo_verified)
+      {
+      HDEBUG(D_receive) debug_printf("matched host name\n");
+      }
+    else
+      {
+      uschar **aliases = sender_host_aliases;
+      while (*aliases != NULL)
+        {
+        helo_verified = strcmpic(*aliases++, sender_helo_name) == 0;
+        if (helo_verified) break;
+        }
+      HDEBUG(D_receive)
+        {
+        if (helo_verified)
+          debug_printf("matched alias %s\n", *(--aliases));
+        }
+      }
+    }
+
+  /* Final attempt: try a forward lookup of the helo name */
+
+  if (!helo_verified)
+    {
+    int rc;
+    host_item h;
+    h.name = sender_helo_name;
+    h.address = NULL;
+    h.mx = MX_NONE;
+    h.next = NULL;
+    HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
+      sender_helo_name);
+    rc = host_find_byname(&h, NULL, NULL, TRUE);
+    if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
+      {
+      host_item *hh = &h;
+      while (hh != NULL)
+        {
+        if (Ustrcmp(hh->address, sender_host_address) == 0)
+          {
+          helo_verified = TRUE;
+          HDEBUG(D_receive)
+            debug_printf("IP address for %s matches calling address\n",
+              sender_helo_name);
+          break;
+          }
+        hh = hh->next;
+        }
+      }
+    }
+  }
+
+if (!helo_verified) helo_verify_failed = FALSE;  /* We've tried ... */
+return yield;
+}
+
+
+
+
 /*************************************************
 *       Initialize for SMTP incoming message     *
 *************************************************/
@@ -2278,104 +2406,16 @@ while (done <= 0)
         (tls_active >= 0)? " TLS" : "", host_and_ident(FALSE));
 
       /* Verify if configured. This doesn't give much security, but it does
-      make some people happy to be able to do it. Note that HELO is legitimately
-      allowed to quote an address literal. Allow for IPv6 ::ffff: literals. */
+      make some people happy to be able to do it. If helo_required is set,
+      (host matches helo_verify_hosts) failure forces rejection. If helo_verify
+      is set (host matches helo_try_verify_hosts), it does not. This is perhaps
+      now obsolescent, since the verification can now be requested selectively
+      at ACL time. */
 
-      helo_verified = FALSE;
+      helo_verified = helo_verify_failed = FALSE;
       if (helo_required || helo_verify)
         {
-        BOOL tempfail = FALSE;
-
-        HDEBUG(D_receive) debug_printf("verifying %s %s\n", hello,
-          sender_helo_name);
-        if (sender_helo_name[0] == '[')
-          {
-          helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address,
-            Ustrlen(sender_host_address)) == 0;
-
-          #if HAVE_IPV6
-          if (!helo_verified)
-            {
-            if (strncmpic(sender_host_address, US"::ffff:", 7) == 0)
-              helo_verified = Ustrncmp(sender_helo_name + 1,
-                sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0;
-            }
-          #endif
-
-          HDEBUG(D_receive)
-            { if (helo_verified) debug_printf("matched host address\n"); }
-          }
-
-        /* Do a reverse lookup if one hasn't already given a positive or
-        negative response. If that fails, or the name doesn't match, try
-        checking with a forward lookup. */
-
-        else
-          {
-          if (sender_host_name == NULL && !host_lookup_failed)
-            tempfail = host_name_lookup() == DEFER;
-
-          /* If a host name is known, check it and all its aliases. */
-
-          if (sender_host_name != NULL)
-            {
-            helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0;
-
-            if (helo_verified)
-              {
-              HDEBUG(D_receive) debug_printf("matched host name\n");
-              }
-            else
-              {
-              uschar **aliases = sender_host_aliases;
-              while (*aliases != NULL)
-                {
-                helo_verified = strcmpic(*aliases++, sender_helo_name) == 0;
-                if (helo_verified) break;
-                }
-              HDEBUG(D_receive)
-                {
-                if (helo_verified)
-                  debug_printf("matched alias %s\n", *(--aliases));
-                }
-              }
-            }
-
-          /* Final attempt: try a forward lookup of the helo name */
-
-          if (!helo_verified)
-            {
-            int rc;
-            host_item h;
-            h.name = sender_helo_name;
-            h.address = NULL;
-            h.mx = MX_NONE;
-            h.next = NULL;
-            HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
-              sender_helo_name);
-            rc = host_find_byname(&h, NULL, NULL, TRUE);
-            if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
-              {
-              host_item *hh = &h;
-              while (hh != NULL)
-                {
-                if (Ustrcmp(hh->address, sender_host_address) == 0)
-                  {
-                  helo_verified = TRUE;
-                  HDEBUG(D_receive)
-                    debug_printf("IP address for %s matches calling address\n",
-                      sender_helo_name);
-                  break;
-                  }
-                hh = hh->next;
-                }
-              }
-            }
-          }
-
-        /* Verification failed. A temporary lookup failure gives a temporary
-        error. */
-
+        BOOL tempfail = !smtp_verify_helo();
         if (!helo_verified)
           {
           if (helo_required)
@@ -2589,7 +2629,7 @@ while (done <= 0)
     if (tls_active >= 0) (void)tls_write(s, ptr); else
     #endif
 
-    fwrite(s, 1, ptr, smtp_out);
+    (void)fwrite(s, 1, ptr, smtp_out);
     DEBUG(D_receive) debug_printf("SMTP>> %s", s);
     helo_seen = TRUE;
     break;   /* HELO/EHLO */
@@ -3479,9 +3519,9 @@ while (done <= 0)
 
     if ((pid = fork()) == 0)
       {
-      smtp_input = FALSE;    /* This process is not associated with the */
-      fclose(smtp_in);       /* SMTP call any more. */
-      fclose(smtp_out);
+      smtp_input = FALSE;       /* This process is not associated with the */
+      (void)fclose(smtp_in);    /* SMTP call any more. */
+      (void)fclose(smtp_out);
 
       signal(SIGCHLD, SIG_DFL);      /* Want to catch child */
 
@@ -3558,8 +3598,7 @@ while (done <= 0)
     if (c > 150) c = 150;
     smtp_inptr[c] = 0;
     incomplete_transaction_log(US"sync failure");
-    log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: "
-      "synchronization error "
+    log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol synchronization error "
       "(next input sent too soon: pipelining was%s advertised): "
       "rejected \"%s\" %s next input=\"%s\"",
       pipelining_advertised? "" : " not",