Note about ratelimit resets.
[exim.git] / src / src / match.c
index 18787e8acd63c95fcbe060c2bd0c31a114ba9b21..01b52ed0e0c77bb49e2d179a5166a34095a55078 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/match.c,v 1.9 2005/09/12 13:39:31 ph10 Exp $ */
+/* $Cambridge: exim/src/src/match.c,v 1.17 2007/01/08 10:50:18 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for matching strings */
@@ -74,7 +74,8 @@ Arguments:
                    returns ERROR)
 
 Contents of the argument block:
-  subject        the subject string to be checked
+  origsubject    the subject in its original casing
+  subject        the subject string to be checked, lowercased if caseless
   expand_setup   if < 0, don't set up any numeric expansion variables;
                  if = 0, set $0 to whole subject, and either
                    $1 to what matches * or
@@ -99,7 +100,7 @@ check_string_block *cb = (check_string_block *)arg;
 int search_type, partial, affixlen, starflags;
 int expand_setup = cb->expand_setup;
 uschar *affix;
-uschar *s = cb->subject;
+uschar *s;
 uschar *filename = NULL;
 uschar *keyquery, *result, *semicolon;
 void *handle;
@@ -108,6 +109,12 @@ error = error;  /* Keep clever compilers from complaining */
 
 if (valueptr != NULL) *valueptr = NULL;  /* For non-lookup matches */
 
+/* For regular expressions, use cb->origsubject rather than cb->subject so that
+it works if the pattern uses (?-i) to turn off case-independence, overriding
+"caseless". */
+
+s = (pattern[0] == '^')? cb->origsubject : cb->subject;
+
 /* If required to set up $0, initialize the data but don't turn on by setting
 expand_nmax until the match is assured. */
 
@@ -174,7 +181,9 @@ if (cb->at_is_special && pattern[0] == '@')
     int slen = Ustrlen(s);
     if (s[0] != '[' && s[slen-1] != ']') return FAIL;
     for (ip = host_find_interfaces(); ip != NULL; ip = ip->next)
-      if (Ustrncmp(ip->address, s+1, slen - 2) == 0) return OK;
+      if (Ustrncmp(ip->address, s+1, slen - 2) == 0
+            && ip->address[slen - 2] == 0)
+        return OK;
     return FAIL;
     }
 
@@ -423,7 +432,7 @@ Returns:       OK    if matched a non-negated item
                FAIL  if expansion force-failed
                FAIL  if matched a negated item
                FAIL  if hit end of list after a non-negated item
-               DEFER if a lookup deferred or expansion failed
+               DEFER if a something deferred or expansion failed
 */
 
 int
@@ -472,7 +481,19 @@ if (type >= MCL_NOEXPAND)
   }
 else
   {
-  list = expand_string(*listptr);
+  /* If we are searching a domain list, and $domain is not set, set it to the
+  subject that is being sought for the duration of the expansion. */
+
+  if (type == MCL_DOMAIN && deliver_domain == NULL)
+    {
+    check_string_block *cb = (check_string_block *)arg;
+    deliver_domain = cb->subject;
+    list = expand_string(*listptr);
+    deliver_domain = NULL;
+    }
+
+  else list = expand_string(*listptr);
+
   if (list == NULL)
     {
     if (expand_string_forcedfail)
@@ -713,7 +734,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         case ERROR:
         if (ignore_unknown)
           {
-          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown",
+          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n",
             error);
           }
         else
@@ -808,7 +829,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         case ERROR:          /* host name lookup failed - this can only */
         if (ignore_unknown)  /* be for an incoming host (not outgoing) */
           {
-          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown",
+          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n",
             error);
           }
         else
@@ -842,10 +863,10 @@ HDEBUG(D_lists)
   debug_printf("%s %s (end of list)\n", ot, (yield == OK)? "no":"yes");
 return (yield == OK)? FAIL : OK;
 
-/* Handle lookup defer */
+/* Something deferred */
 
 DEFER_RETURN:
-HDEBUG(D_lists) debug_printf("%s lookup deferred for %s\n", ot, sss);
+HDEBUG(D_lists) debug_printf("%s list match deferred for %s\n", ot, sss);
 return DEFER;
 }
 
@@ -953,6 +974,20 @@ error = error;  /* Keep clever compilers from complaining */
 DEBUG(D_lists) debug_printf("address match: subject=%s pattern=%s\n",
   subject, pattern);
 
+/* Find the subject's domain */
+
+sdomain = Ustrrchr(subject, '@');
+
+/* The only case where a subject may not have a domain is if the subject is
+empty. Otherwise, a subject with no domain is a serious configuration error. */
+
+if (sdomain == NULL && *subject != 0)
+  {
+  log_write(0, LOG_MAIN|LOG_PANIC, "no @ found in the subject of an "
+    "address list match: subject=\"%s\" pattern=\"%s\"", subject, pattern);
+  return FAIL;
+  }
+
 /* Handle a regular expression, which must match the entire incoming address.
 This may be the empty address. */
 
@@ -987,10 +1022,6 @@ against. */
 
 if (*subject == 0) return (*pattern == 0)? OK : FAIL;
 
-/* Find the subject's domain */
-
-sdomain = Ustrrchr(subject, '@');
-
 /* If the pattern starts with "@@" we have a split lookup, where the domain is
 looked up to obtain a list of local parts. If the subject's local part is just
 "*" (called from retry) the match always fails. */