Make lockfile_mode apply to MBX lock files.
[exim.git] / src / src / smtp_in.c
index 4ed335c02da40c83a0adf51ce7f8f5d722778ee7..99ac3fb1a3f402f866aa47163ef01c2cf510e2bf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.33 2006/02/14 14:55:37 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    *
@@ -338,8 +338,13 @@ va_list ap;
 
 DEBUG(D_receive)
   {
+  uschar *cr, *end;
   va_start(ap, format);
   (void) string_vformat(big_buffer, big_buffer_size, format, ap);
+  va_end(ap);
+  end = big_buffer + Ustrlen(big_buffer);
+  while ((cr = Ustrchr(big_buffer, '\r')) != NULL)   /* lose CRs */
+    memmove(cr, cr + 1, (end--) - cr);
   debug_printf("SMTP>> %s", big_buffer);
   }
 
@@ -808,7 +813,7 @@ rcpt_count = rcpt_defer_count = rcpt_fail_count =
   raw_recipients_count = recipients_count = recipients_list_max = 0;
 message_linecount = 0;
 message_size = -1;
-acl_warn_headers = NULL;
+acl_added_headers = NULL;
 queue_only_policy = FALSE;
 deliver_freeze = FALSE;                              /* Can be set by ACL */
 freeze_tell = freeze_tell_config;                    /* Can be set by ACL */
@@ -1454,19 +1459,40 @@ if (!sender_host_unknown)
     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
+  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))
     {
-    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
@@ -2147,10 +2173,14 @@ while (done <= 0)
   switch(smtp_read_command(TRUE))
     {
     /* The AUTH command is not permitted to occur inside a transaction, and may
-    occur successfully only once per connection, and then only when we've
-    advertised it. Actually, that isn't quite true. When TLS is started, all
-    previous information about a connection must be discarded, so a new AUTH is
-    permitted at that time.
+    occur successfully only once per connection. Actually, that isn't quite
+    true. When TLS is started, all previous information about a connection must
+    be discarded, so a new AUTH is permitted at that time.
+
+    AUTH may only be used when it has been advertised. However, it seems that
+    there are clients that send AUTH when it hasn't been advertised, some of
+    them even doing this after HELO. And there are MTAs that accept this. Sigh.
+    So there's a get-out that allows this to happen.
 
     AUTH is initially labelled as a "nonmail command" so that one occurrence
     doesn't get counted. We change the label here so that multiple failing
@@ -2160,7 +2190,7 @@ while (done <= 0)
     authentication_failed = TRUE;
     cmd_list[CMD_LIST_AUTH].is_mail_cmd = FALSE;
 
-    if (!auth_advertised)
+    if (!auth_advertised && !allow_auth_unadvertised)
       {
       done = synprot_error(L_smtp_protocol_error, 503, NULL,
         US"AUTH command used when not advertised");
@@ -2215,12 +2245,13 @@ while (done <= 0)
       }
 
     /* Search for an authentication mechanism which is configured for use
-    as a server and which has been advertised. */
+    as a server and which has been advertised (unless, sigh, allow_auth_
+    unadvertised is set). */
 
     for (au = auths; au != NULL; au = au->next)
       {
       if (strcmpic(s, au->public_name) == 0 && au->server &&
-          au->advertised) break;
+          (au->advertised || allow_auth_unadvertised)) break;
       }
 
     if (au == NULL)
@@ -2638,7 +2669,13 @@ while (done <= 0)
     #endif
 
     (void)fwrite(s, 1, ptr, smtp_out);
-    DEBUG(D_receive) debug_printf("SMTP>> %s", s);
+    DEBUG(D_receive)
+      {
+      uschar *cr;
+      while ((cr = Ustrchr(s, '\r')) != NULL)   /* lose CRs */
+        memmove(cr, cr + 1, (ptr--) - (cr - s));
+      debug_printf("SMTP>> %s", s);
+      }
     helo_seen = TRUE;
     break;   /* HELO/EHLO */
 
@@ -3192,14 +3229,14 @@ while (done <= 0)
           break;
 
           case DEFER:
-          s = (addr->message != NULL)?
-            string_sprintf("451 <%s> %s", address, addr->message) :
+          s = (addr->user_message != NULL)?
+            string_sprintf("451 <%s> %s", address, addr->user_message) :
             string_sprintf("451 Cannot resolve <%s> at this time", address);
           break;
 
           case FAIL:
-          s = (addr->message != NULL)?
-            string_sprintf("550 <%s> %s", address, addr->message) :
+          s = (addr->user_message != NULL)?
+            string_sprintf("550 <%s> %s", address, addr->user_message) :
             string_sprintf("550 <%s> is not deliverable", address);
           log_write(0, LOG_MAIN, "VRFY failed for %s %s",
             smtp_cmd_argument, host_and_ident(TRUE));