defer_ok was not working if used on a callout with verify=header_sender.
[exim.git] / src / src / verify.c
index 0c1d6b0..dedc39f 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.7 2004/11/22 11:30:04 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.14 2005/01/27 10:26:14 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2005 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with verifying things. The original code for callout
@@ -377,6 +377,7 @@ for (host = host_list; host != NULL && !done; host = host->next)
   smtp_outblock outblock;
   int host_af;
   int port = 25;
+  BOOL send_quit = TRUE; 
   uschar *helo = US"HELO";
   uschar *interface = NULL;  /* Outgoing interface to use; NULL => any */
   uschar inbuffer[4096];
@@ -609,6 +610,7 @@ for (host = host_list; host != NULL && !done; host = host->next)
     if (errno == ETIMEDOUT)
       {
       HDEBUG(D_verify) debug_printf("SMTP timeout\n");
+      send_quit = FALSE; 
       }
     else if (errno == 0)
       {
@@ -637,7 +639,7 @@ for (host = host_list; host != NULL && !done; host = host->next)
 
   /* End the SMTP conversation and close the connection. */
 
-  (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n");
+  if (send_quit) (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n");
   close(inblock.sock);
   }    /* Loop through all hosts, while !done */
 
@@ -1049,7 +1051,8 @@ while (addr_new != NULL)
             for (host = host_list; host != NULL; host = nexthost)
               {
               nexthost = host->next;
-              if (tf.gethostbyname || string_is_ip_address(host->name, NULL))
+              if (tf.gethostbyname || 
+                  string_is_ip_address(host->name, NULL) > 0)
                 (void)host_find_byname(host, NULL, &canonical_name, TRUE);
               else
                 {
@@ -1099,7 +1102,7 @@ while (addr_new != NULL)
   want to continue to verify the new child. */
 
   if (rc == REROUTED) continue;
-
+  
   /* Handle hard failures */
 
   if (rc == FAIL)
@@ -1462,6 +1465,7 @@ Arguments:
   se_mailfrom      mailfrom for verify; NULL => ""
   pm_mailfrom      sender for pm callout check (passed to verify_address())
   options          callout options (passed to verify_address())
+  verrno           where to put the address basic_errno 
 
 If log_msgptr is set to something without setting user_msgptr, the caller
 normally uses log_msgptr for both things.
@@ -1473,7 +1477,7 @@ Returns:           result of the verification attempt: OK, FAIL, or DEFER;
 int
 verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr,
   int callout, int callout_overall, int callout_connect, uschar *se_mailfrom, 
-  uschar *pm_mailfrom, int options)
+  uschar *pm_mailfrom, int options, int *verrno)
 {
 static int header_types[] = { htype_sender, htype_reply_to, htype_from };
 int yield = FAIL;
@@ -1554,7 +1558,7 @@ for (i = 0; i < 3; i++)
             }
           }
 
-        /* Else go ahead with the sender verification. But is isn't *the*
+        /* Else go ahead with the sender verification. But it isn't *the*
         sender of the message, so set vopt_fake_sender to stop sender_address
         being replaced after rewriting or qualification. */
 
@@ -1572,12 +1576,16 @@ for (i = 0; i < 3; i++)
       last of these will be returned to the user if all three fail. We do not
       set a log message - the generic one below will be used. */
 
-      if (new_ok != OK && smtp_return_error_details)
+      if (new_ok != OK)
         {
-        *user_msgptr = string_sprintf("Rejected after DATA: "
-          "could not verify \"%.*s\" header address\n%s: %s",
-          endname - h->text, h->text, vaddr->address, vaddr->message);
-        }
+        *verrno = vaddr->basic_errno; 
+        if (smtp_return_error_details)
+          {
+          *user_msgptr = string_sprintf("Rejected after DATA: "
+            "could not verify \"%.*s\" header address\n%s: %s",
+            endname - h->text, h->text, vaddr->address, vaddr->message);
+          }
+        }   
 
       /* Success or defer */
 
@@ -1830,7 +1838,7 @@ if (*ss == '@')
 /* If the pattern is an IP address, optionally followed by a bitmask count, do
 a (possibly masked) comparision with the current IP address. */
 
-if (string_is_ip_address(ss, &maskoffset))
+if (string_is_ip_address(ss, &maskoffset) > 0)
   return (host_is_in_net(cb->host_address, ss, maskoffset)? OK : FAIL);
 
 /* If the item is of the form net[n]-lookup;<file|query> then it is a lookup on
@@ -2593,13 +2601,14 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
   else
     {
     int keysep = 0;
+    BOOL defer = FALSE; 
     uschar *keydomain; 
     uschar keybuffer[256];
   
     while ((keydomain = string_nextinlist(&key, &keysep, keybuffer, 
             sizeof(keybuffer))) != NULL)
       {       
-      if (string_is_ip_address(keydomain, NULL))
+      if (string_is_ip_address(keydomain, NULL) > 0)
         {
         uschar keyrevadd[128];
         invert_address(keyrevadd, keydomain);
@@ -2625,11 +2634,17 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
         dnslist_domain = string_copy(domain);
         HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n", 
           keydomain, domain);
+        return OK;   
         }
          
-      if (rc != FAIL) return rc;   /* OK or DEFER */
+      /* If the lookup deferred, remember this fact. We keep trying the rest
+      of the list to see if we get a useful result, and if we don't, we return
+      DEFER at the end. */
 
+      if (rc == DEFER) defer = TRUE;
       }    /* continue with next keystring domain/address */
+
+    if (defer) return DEFER;
     }  
   }        /* continue with next dnsdb outer domain */