Kludge for tcp-wrappers problem during system catastrophes.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Wed, 19 Apr 2006 10:58:21 +0000 (10:58 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Wed, 19 Apr 2006 10:58:21 +0000 (10:58 +0000)
doc/doc-txt/ChangeLog
src/src/smtp_in.c

index d69e9eafbfa1111338dd2cb432c1c5ecd205721a..56d0822fd6d85d883ad7d45241a16087611c84b8 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.340 2006/04/18 11:13:19 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.341 2006/04/19 10:58:21 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -12,6 +12,16 @@ TF/01 Fix the add_header change below (4.61 PH/55) which had a bug that (amongst
 PH/01 ${readsocket now supports Internet domain sockets (modified John Jetmore
       patch).
 
 PH/01 ${readsocket now supports Internet domain sockets (modified John Jetmore
       patch).
 
+PH/02 When tcp-wrappers is called from Exim, it returns only "deny" or "allow".
+      "Deny" causes Exim to reject the incoming connection with a 554 error.
+      Unfortunately, if there is a major crisis, such as a disk failure,
+      tcp-wrappers gives "deny", whereas what one would like would be some
+      kind of temporary error. A kludge has been added to help with this.
+      Before calling hosts_ctl(), errno is set zero. If the result is "deny", a
+      554 error is used if errno is still zero or contains ENOENT (which occurs
+      if either of the /etc/hosts.{allow,deny} files is missing). Otherwise, a
+      451 error is used.
+
 
 Exim version 4.61
 -----------------
 
 Exim version 4.61
 -----------------
index e832358363fdf7da7059ced753d6dace571eebbc..99ac3fb1a3f402f866aa47163ef01c2cf510e2bf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.37 2006/03/16 11:14:46 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.38 2006/04/19 10:58:21 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1459,19 +1459,40 @@ if (!sender_host_unknown)
     return FALSE;
     }
 
     return FALSE;
     }
 
-  /* Test with TCP Wrappers if so configured */
+  /* Test with TCP Wrappers if so configured. There is a problem in that
+  hosts_ctl() returns 0 (deny) under a number of system failure circumstances,
+  such as disks dying. In these cases, it is desirable to reject with a 4xx
+  error instead of a 5xx error. There isn't a "right" way to detect such
+  problems. The following kludge is used: errno is zeroed before calling
+  hosts_ctl(). If the result is "reject", a 5xx error is given only if the
+  value of errno is 0 or ENOENT (which happens if /etc/hosts.{allow,deny} does
+  not exist). */
 
   #ifdef USE_TCP_WRAPPERS
 
   #ifdef USE_TCP_WRAPPERS
+  errno = 0;
   if (!hosts_ctl("exim",
          (sender_host_name == NULL)? STRING_UNKNOWN : CS sender_host_name,
          (sender_host_address == NULL)? STRING_UNKNOWN : CS sender_host_address,
          (sender_ident == NULL)? STRING_UNKNOWN : CS sender_ident))
     {
   if (!hosts_ctl("exim",
          (sender_host_name == NULL)? STRING_UNKNOWN : CS sender_host_name,
          (sender_host_address == NULL)? STRING_UNKNOWN : CS sender_host_address,
          (sender_ident == NULL)? STRING_UNKNOWN : CS sender_ident))
     {
-    HDEBUG(D_receive) debug_printf("tcp wrappers rejection\n");
-    log_write(L_connection_reject,
-              LOG_MAIN|LOG_REJECT, "refused connection from %s "
-              "(tcp wrappers)", host_and_ident(FALSE));
-    smtp_printf("554 SMTP service not available\r\n");
+    if (errno == 0 || errno == ENOENT)
+      {
+      HDEBUG(D_receive) debug_printf("tcp wrappers rejection\n");
+      log_write(L_connection_reject,
+                LOG_MAIN|LOG_REJECT, "refused connection from %s "
+                "(tcp wrappers)", host_and_ident(FALSE));
+      smtp_printf("554 SMTP service not available\r\n");
+      }
+    else
+      {
+      int save_errno = errno;
+      HDEBUG(D_receive) debug_printf("tcp wrappers rejected with unexpected "
+        "errno value %d\n", save_errno);
+      log_write(L_connection_reject,
+                LOG_MAIN|LOG_REJECT, "temporarily refused connection from %s "
+                "(tcp wrappers errno=%d)", host_and_ident(FALSE), save_errno);
+      smtp_printf("451 Temporary local problem - please try later\r\n");
+      }
     return FALSE;
     }
   #endif
     return FALSE;
     }
   #endif