Fix matching of long addresses. Bug 2677
[exim.git] / src / src / match.c
index db02b37bd519c3c050e8aa413681361b00a0dc9f..bf8cb3b98f8331700c187a9430ad8ebd9034b568 100644 (file)
@@ -104,9 +104,7 @@ uschar *filename = NULL;
 uschar *keyquery, *result, *semicolon;
 void *handle;
 
-error = error;  /* Keep clever compilers from complaining */
-
-if (valueptr != NULL) *valueptr = NULL;  /* For non-lookup matches */
+if (valueptr) *valueptr = NULL;
 
 /* 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
@@ -136,7 +134,6 @@ if (pattern[0] == '^')
       : !regex_match_and_setup(re, s, 0, expand_setup)
      )
     return FAIL;
-  /* assume the above wrote $0, $n... TODO: CHECK THAT !! */
   if (valueptr) *valueptr = pattern;   /* "value" gets the RE */
   return OK;
   }
@@ -158,9 +155,9 @@ if (pattern[0] == '*')
     {
     expand_nstring[++expand_setup] = s;                /* write a $n, the matched subject variable-part */
     expand_nlength[expand_setup] = slen - patlen;
-    expand_nmax = expand_setup;
+    expand_nmax = expand_setup;                        /* commit also $0, the matched subject */
     }
-  if (valueptr) *valueptr = pattern;   /* "value" gets the pattern */
+  if (valueptr) *valueptr = pattern - 1;       /* "value" gets the (original) pattern */
   return OK;
   }
 
@@ -185,7 +182,7 @@ if (cb->at_is_special && pattern[0] == '@')
       if (Ustrncmp(ip->address, s+1, slen - 2) == 0
             && ip->address[slen - 2] == 0)
        {
-/* I see no reason not to return $0, the matchd IP.  if (expand_setup >= 0) expand_nmax = expand_setup; */
+       if (expand_setup >= 0) expand_nmax = expand_setup;      /* commit $0, the IP addr */
        if (valueptr) *valueptr = pattern;      /* "value" gets the pattern */
         return OK;
        }
@@ -238,11 +235,11 @@ if (cb->at_is_special && pattern[0] == '@')
       return DEFER;
       }
 
-    if (rc != HOST_FOUND_LOCAL || secy)
-      if (prim || !removed) return FAIL;
+    if ((rc != HOST_FOUND_LOCAL || secy) && (prim || !removed))
+      return FAIL;
 
-/* again, $0 getting the subject, the matched IP.  if (expand_setup >= 0) expand_nmax = expand_setup; */
-    if (valueptr) *valueptr = pattern; /* "vaulue" gets the patterm */
+    if (expand_setup >= 0) expand_nmax = expand_setup; /* commit $0, the matched subject */
+    if (valueptr) *valueptr = pattern; /* "value" gets the patterm */
     return OK;
 
     /*** The above line used to be the following line, but this is incorrect,
@@ -268,10 +265,6 @@ if ((semicolon = Ustrchr(pattern, ';')) == NULL)
   if (expand_setup >= 0) expand_nmax = expand_setup;   /* Original code!   $0 gets the matched subject */
   if (valueptr) *valueptr = pattern;   /* "value" gets the pattern */
   return OK;
-
-/*
-XXX  looks like $0 may be usable
-*/
   }
 
 /* Otherwise we have a lookup item. The lookup type, including partial, etc. is
@@ -291,22 +284,7 @@ if (!cb->use_partial) partial = -1;
 
 /* Set the parameters for the three different kinds of lookup. */
 
-keyquery = semicolon + 1;
-Uskip_whitespace(&keyquery);
-
-if (mac_islookup(search_type, lookup_absfilequery))
-  {
-  filename = keyquery;
-  while (*keyquery && !isspace(*keyquery)) keyquery++;
-  filename = string_copyn(filename, keyquery - filename);
-  Uskip_whitespace(&keyquery);
-  }
-
-else if (!mac_islookup(search_type, lookup_querystyle))
-  {
-  filename = keyquery;
-  keyquery = s;
-  }
+keyquery = search_args(search_type, s, semicolon+1, &filename, opts);
 
 /* Now do the actual lookup; throw away the data returned unless it was asked
 for; partial matching is all handled inside search_find(). Note that there is
@@ -355,7 +333,7 @@ match_check_string(const uschar *s, const uschar *pattern, int expand_setup,
 {
 check_string_block cb;
 cb.origsubject = s;
-cb.subject = caseless? string_copylc(s) : string_copy(s);
+cb.subject = caseless ? string_copylc(s) : string_copy(s);
 cb.expand_setup = expand_setup;
 cb.use_partial = use_partial;
 cb.caseless = caseless;
@@ -808,7 +786,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
       if (listname[0] == 0)
         listname = string_sprintf("\"%s\"", *listptr);
       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
-        string_open_failed(errno, "%s when checking %s", sss, listname));
+        string_open_failed("%s when checking %s", sss, listname));
       }
 
     /* Trailing comments are introduced by #, but in an address list or local
@@ -966,12 +944,17 @@ match_isinlist(const uschar *s, const uschar **listptr, int sep,
 unsigned int *local_cache_bits = cache_bits;
 check_string_block cb;
 cb.origsubject = s;
-cb.subject = caseless? string_copylc(s) : string_copy(s);
-cb.expand_setup = (sep > UCHAR_MAX)? 0 : -1;
+cb.subject = caseless ? string_copylc(s) : string_copy(s);
+cb.at_is_special = FALSE;
+switch (type & ~MCL_NOEXPAND)
+  {
+  case MCL_DOMAIN:     cb.at_is_special = TRUE;        /*FALLTHROUGH*/
+  case MCL_LOCALPART:  cb.expand_setup = 0;                            break;
+  default:             cb.expand_setup = sep > UCHAR_MAX ? 0 : -1;     break;
+  }
 cb.use_partial = TRUE;
 cb.caseless = caseless;
-cb.at_is_special = (type == MCL_DOMAIN || type == MCL_DOMAIN + MCL_NOEXPAND);
-if (valueptr != NULL) *valueptr = NULL;
+if (valueptr) *valueptr = NULL;
 return  match_check_list(listptr, sep, anchorptr, &local_cache_bits,
   check_string, &cb, type, s, valueptr);
 }
@@ -1019,8 +1002,6 @@ uschar *subject = cb->address;
 const uschar *s;
 uschar *pdomain, *sdomain;
 
-error = error;  /* Keep clever compilers from complaining */
-
 DEBUG(D_lists) debug_printf("address match test: subject=%s pattern=%s\n",
   subject, pattern);
 
@@ -1288,9 +1269,11 @@ compared. Therefore, Exim now forces the entire address into lower case here,
 provided that "caseless" is set. (It is FALSE for calls for matching rewriting
 patterns.) Otherwise just the domain is lower cases. A magic item "+caseful" in
 the list can be used to restore a caseful copy of the local part from the
-original address. */
+original address.
+Limit the subject address size to avoid mem-exhastion attacks.  The size chosen
+is historical (we used to use big_buffer her). */
 
-if ((len = Ustrlen(address)) > 255) len = 255;
+if ((len = Ustrlen(address)) > BIG_BUFFER_SIZE) len = BIG_BUFFER_SIZE;
 ab.address = string_copyn(address, len);
 
 for (uschar * p = ab.address + len - 1; p >= ab.address; p--)