Update version number and copyright year.
[exim.git] / src / src / verify.c
index 4d0fe69d2f2a526bc03485ac37e663ee2ebd3f7c..141446aa7d5a7bbc288bd286d0aca7047a357ba1 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.41 2006/10/03 15:11:22 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.45 2007/01/08 10:50:18 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with verifying things. The original code for callout
@@ -441,9 +441,10 @@ for (host = host_list; host != NULL && !done; host = host->next)
   if (tf->helo_data != NULL)
     {
     uschar *s = expand_string(tf->helo_data);
-    if (active_hostname == NULL)
+    if (s == NULL)
       log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: failed to expand transport's "
-        "helo_data value for callout: %s", expand_string_message);
+        "helo_data value for callout: %s", addr->address,
+        expand_string_message);
     else active_hostname = s;
     }
 
@@ -1009,17 +1010,11 @@ information about the top level address, not anything that it generated. */
 while (addr_new != NULL)
   {
   int rc;
-  uschar *show_address;
   address_item *addr = addr_new;
 
   addr_new = addr->next;
   addr->next = NULL;
 
-  /* When full_info is set, child addresses are displayed in top-level
-  messages. Otherwise, we show only the top level address. */
-
-  show_address = full_info? addr->address : address;
-
   DEBUG(D_verify)
     {
     debug_printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
@@ -1141,6 +1136,7 @@ while (addr_new != NULL)
             }
           else
             {
+            int flags;
             uschar *canonical_name;
             host_item *host, *nexthost;
             host_build_hostlist(&host_list, s, tf.hosts_randomize);
@@ -1151,20 +1147,19 @@ while (addr_new != NULL)
             additional host items being inserted into the chain. Hence we must
             save the next host first. */
 
+            flags = HOST_FIND_BY_A;
+            if (tf.qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
+            if (tf.search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
+
             for (host = host_list; host != NULL; host = nexthost)
               {
               nexthost = host->next;
               if (tf.gethostbyname ||
                   string_is_ip_address(host->name, NULL) != 0)
-                (void)host_find_byname(host, NULL, &canonical_name, TRUE);
+                (void)host_find_byname(host, NULL, flags, &canonical_name, TRUE);
               else
-                {
-                int flags = HOST_FIND_BY_A;
-                if (tf.qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE;
-                if (tf.search_parents) flags |= HOST_FIND_SEARCH_PARENTS;
                 (void)host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
                   &canonical_name, NULL);
-                }
               }
             }
           }
@@ -1215,7 +1210,7 @@ while (addr_new != NULL)
       {
       address_item *p = addr->parent;
 
-      fprintf(f, "%s%s %s", ko_prefix, show_address,
+      fprintf(f, "%s%s %s", ko_prefix, full_info? addr->address : address,
         address_test_mode? "is undeliverable" : "failed to verify");
       if (!expn && admin_user)
         {
@@ -1248,7 +1243,7 @@ while (addr_new != NULL)
       {
       address_item *p = addr->parent;
       fprintf(f, "%s%s cannot be resolved at this time", ko_prefix,
-        show_address);
+        full_info? addr->address : address);
       if (!expn && admin_user)
         {
         if (addr->basic_errno > 0)
@@ -1321,7 +1316,7 @@ while (addr_new != NULL)
          (addr_new != NULL &&            /* At least one new address AND */
           success_on_redirect)))         /* success_on_redirect is set */
       {
-      if (f != NULL) fprintf(f, "%s %s\n", show_address,
+      if (f != NULL) fprintf(f, "%s %s\n", address,
         address_test_mode? "is deliverable" : "verified");
 
       /* If we have carried on to verify a child address, we want the value
@@ -1457,8 +1452,9 @@ verify_check_headers(uschar **msgptr)
 {
 header_line *h;
 uschar *colon, *s;
+int yield = OK;
 
-for (h = header_list; h != NULL; h = h->next)
+for (h = header_list; h != NULL && yield == OK; h = h->next)
   {
   if (h->type != htype_from &&
       h->type != htype_reply_to &&
@@ -1472,9 +1468,10 @@ for (h = header_list; h != NULL; h = h->next)
   s = colon + 1;
   while (isspace(*s)) s++;
 
-  parse_allow_group = TRUE;     /* Allow group syntax */
+  /* Loop for multiple addresses in the header, enabling group syntax. Note
+  that we have to reset this after the header has been scanned. */
 
-  /* Loop for multiple addresses in the header */
+  parse_allow_group = TRUE;
 
   while (*s != 0)
     {
@@ -1484,7 +1481,7 @@ for (h = header_list; h != NULL; h = h->next)
     int start, end, domain;
 
     /* Temporarily terminate the string at this point, and extract the
-    operative address within. */
+    operative address within, allowing group syntax. */
 
     *ss = 0;
     recipient = parse_extract_address(s,&errmess,&start,&end,&domain,FALSE);
@@ -1540,7 +1537,8 @@ for (h = header_list; h != NULL; h = h->next)
         string_sprintf("%s: failing address in \"%.*s:\" header %s: %.*s",
           errmess, tt - h->text, h->text, verb, len, s));
 
-      return FAIL;
+      yield = FAIL;
+      break;          /* Out of address loop */
       }
 
     /* Advance to the next address */
@@ -1548,9 +1546,12 @@ for (h = header_list; h != NULL; h = h->next)
     s = ss + (terminator? 1:0);
     while (isspace(*s)) s++;
     }   /* Next address */
-  }     /* Next header */
 
-return OK;
+  parse_allow_group = FALSE;
+  parse_found_group = FALSE;
+  }     /* Next header unless yield has been set FALSE */
+
+return yield;
 }
 
 
@@ -1593,9 +1594,10 @@ for (i = 0; i < recipients_count; i++)
     s = colon + 1;
     while (isspace(*s)) s++;
 
-    parse_allow_group = TRUE;     /* Allow group syntax */
+    /* Loop for multiple addresses in the header, enabling group syntax. Note
+    that we have to reset this after the header has been scanned. */
 
-    /* Loop for multiple addresses in the header */
+    parse_allow_group = TRUE;
 
     while (*s != 0)
       {
@@ -1605,7 +1607,7 @@ for (i = 0; i < recipients_count; i++)
       int start, end, domain;
 
       /* Temporarily terminate the string at this point, and extract the
-      operative address within. */
+      operative address within, allowing group syntax. */
 
       *ss = 0;
       recipient = parse_extract_address(s,&errmess,&start,&end,&domain,FALSE);
@@ -1629,6 +1631,9 @@ for (i = 0; i < recipients_count; i++)
       s = ss + (terminator? 1:0);
       while (isspace(*s)) s++;
       }   /* Next address */
+
+    parse_allow_group = FALSE;
+    parse_found_group = FALSE;
     }     /* Next header (if found is false) */
 
   if (!found) return FAIL;
@@ -1711,13 +1716,14 @@ verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr,
   uschar *pm_mailfrom, int options, int *verrno)
 {
 static int header_types[] = { htype_sender, htype_reply_to, htype_from };
+BOOL done = FALSE;
 int yield = FAIL;
 int i;
 
-for (i = 0; i < 3; i++)
+for (i = 0; i < 3 && !done; i++)
   {
   header_line *h;
-  for (h = header_list; h != NULL; h = h->next)
+  for (h = header_list; h != NULL && !done; h = h->next)
     {
     int terminator, new_ok;
     uschar *s, *ss, *endname;
@@ -1725,6 +1731,11 @@ for (i = 0; i < 3; i++)
     if (h->type != header_types[i]) continue;
     s = endname = Ustrchr(h->text, ':') + 1;
 
+    /* Scan the addresses in the header, enabling group syntax. Note that we
+    have to reset this after the header has been scanned. */
+
+    parse_allow_group = TRUE;
+
     while (*s != 0)
       {
       address_item *vaddr;
@@ -1767,11 +1778,21 @@ for (i = 0; i < 3; i++)
       else
         {
         int start, end, domain;
-        uschar *address = parse_extract_address(s, log_msgptr, &start,
-          &end, &domain, FALSE);
+        uschar *address = parse_extract_address(s, log_msgptr, &start, &end,
+          &domain, FALSE);
 
         *ss = terminator;
 
+        /* If we found an empty address, just carry on with the next one, but
+        kill the message. */
+
+        if (address == NULL && Ustrcmp(*log_msgptr, "empty address") == 0)
+          {
+          *log_msgptr = NULL;
+          s = ss;
+          continue;
+          }
+
         /* If verification failed because of a syntax error, fail this
         function, and ensure that the failing address gets added to the error
         message. */
@@ -1779,14 +1800,13 @@ for (i = 0; i < 3; i++)
         if (address == NULL)
           {
           new_ok = FAIL;
-          if (*log_msgptr != NULL)
-            {
-            while (ss > s && isspace(ss[-1])) ss--;
-            *log_msgptr = string_sprintf("syntax error in '%.*s' header when "
-              "scanning for sender: %s in \"%.*s\"",
-              endname - h->text, h->text, *log_msgptr, ss - s, s);
-            return FAIL;
-            }
+          while (ss > s && isspace(ss[-1])) ss--;
+          *log_msgptr = string_sprintf("syntax error in '%.*s' header when "
+            "scanning for sender: %s in \"%.*s\"",
+            endname - h->text, h->text, *log_msgptr, ss - s, s);
+          yield = FAIL;
+          done = TRUE;
+          break;
           }
 
         /* Else go ahead with the sender verification. But it isn't *the*
@@ -1820,15 +1840,24 @@ for (i = 0; i < 3; i++)
 
       /* Success or defer */
 
-      if (new_ok == OK) return OK;
+      if (new_ok == OK)
+        {
+        yield = OK;
+        done = TRUE;
+        break;
+        }
+
       if (new_ok == DEFER) yield = DEFER;
 
       /* Move on to any more addresses in the header */
 
       s = ss;
-      }
-    }
-  }
+      }     /* Next address */
+
+    parse_allow_group = FALSE;
+    parse_found_group = FALSE;
+    }       /* Next header, unless done */
+  }         /* Next header type unless done */
 
 if (yield == FAIL && *log_msgptr == NULL)
   *log_msgptr = US"there is no valid sender in any header line";
@@ -2223,7 +2252,7 @@ if (*t == 0)
   h.address = NULL;
   h.mx = MX_NONE;
 
-  rc = host_find_byname(&h, NULL, NULL, FALSE);
+  rc = host_find_byname(&h, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, FALSE);
   if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
     {
     host_item *hh;