5670388eaa1ebf55c2558a9a41d1f981241c9cb9
[exim.git] / src / src / match.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2024 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10 /* Functions for matching strings */
11
12
13 #include "exim.h"
14
15
16 /* Argument block for the check_string() function. This is used for general
17 strings, domains, and local parts. */
18
19 typedef struct check_string_block {
20   const uschar *origsubject;           /* caseful; keep these two first, in */
21   const uschar *subject;               /* step with the block below */
22   int    expand_setup;
23   mcs_flags flags;                      /* MCS_* defs in macros.h */
24 } check_string_block;
25
26
27 /* Argument block for the check_address() function. This is used for whole
28 addresses. */
29
30 typedef struct check_address_block {
31   const uschar *origaddress;         /* caseful; keep these two first, in */
32   uschar *address;                   /* step with the block above */
33   int    expand_setup;
34   mcs_flags flags;                      /* MCS_CASELESS, MCS_TEXTONLY_RE */
35 } check_address_block;
36
37
38
39 /*************************************************
40 *           Generalized string match             *
41 *************************************************/
42
43 /* This function does a single match of a subject against a pattern, and
44 optionally sets up the numeric variables according to what it matched. It is
45 called from match_isinlist() via match_check_list() when scanning a list, and
46 from match_check_string() when testing just a single item. The subject and
47 options arguments are passed in a check_string_block so as to make it easier to
48 pass them through match_check_list.
49
50 The possible types of pattern are:
51
52   . regular expression - starts with ^
53   . tail match - starts with *
54   . lookup - starts with search type
55   . if at_is_special is set in the argument block:
56       @              matches the primary host name
57       @[]            matches a local IP address in brackets
58       @mx_any        matches any domain with an MX to the local host
59       @mx_primary    matches any domain with a primary MX to the local host
60       @mx_secondary  matches any domain with a secondary MX to the local host
61   . literal - anything else
62
63 Any of the @mx_xxx options can be followed by "/ignore=<list>" where <list> is
64 a list of IP addresses that are to be ignored (typically 127.0.0.1).
65
66 Arguments:
67   arg            check_string_block pointer - see below
68   pattern        the pattern to be matched
69   valueptr       if not NULL, and a lookup is done, return the result here
70                    instead of discarding it; else set it to point to NULL
71   error          for error messages (not used in this function; it never
72                    returns ERROR)
73
74 Contents of the argument block:
75   origsubject    the subject in its original casing
76   subject        the subject string to be checked, lowercased if caseless
77   expand_setup   if < 0, don't set up any numeric expansion variables;
78                  if = 0, set $0 to whole subject, and either
79                    $1 to what matches * or
80                    $1, $2, ... to r.e. bracketed items
81                  if > 0, don't set $0, but do set either
82                    $n to what matches *, or
83                    $n, $n+1, ... to r.e. bracketed items
84                  (where n = expand_setup)
85   use_partial    if FALSE, override any partial- search types
86   caseless       TRUE for caseless matching where possible
87   at_is_special  enable special handling of items starting with @
88
89 Returns:       OK    if matched
90                FAIL  if not matched
91                DEFER if lookup deferred
92 */
93
94 static int
95 check_string(void * arg, const uschar * pattern, const uschar ** valueptr,
96   uschar ** error)
97 {
98 const check_string_block * cb = arg;
99 int partial, affixlen, starflags;
100 const lookup_info * li;
101 int expand_setup = cb->expand_setup;
102 const uschar * affix, * opts;
103 uschar *s;
104 uschar *filename = NULL;
105 uschar *keyquery, *result, *semicolon;
106 void *handle;
107
108 if (valueptr) *valueptr = NULL;
109
110 /* For regular expressions, use cb->origsubject rather than cb->subject so that
111 it works if the pattern uses (?-i) to turn off case-independence, overriding
112 "caseless". */
113
114 s = string_copy(pattern[0] == '^' ? cb->origsubject : cb->subject);
115
116 /* If required to set up $0, initialize the data but don't turn on by setting
117 expand_nmax until the match is assured. */
118
119 expand_nmax = -1;
120 if (expand_setup == 0)
121   {
122   expand_nstring[0] = s;        /* $0 (might be) the matched subject in full */
123   expand_nlength[0] = Ustrlen(s);
124   }
125 else if (expand_setup > 0) expand_setup--;
126
127 /* Regular expression match: compile, match, and set up $ variables if
128 required. */
129
130 if (pattern[0] == '^')
131   {
132   const pcre2_code * re = regex_must_compile(pattern,
133       cb->flags & (MCS_CACHEABLE | MCS_CASELESS), FALSE);
134   if (expand_setup < 0
135       ? !regex_match(re, s, -1, NULL)
136       : !regex_match_and_setup(re, s, 0, expand_setup)
137      )
138     return FAIL;
139   if (valueptr) *valueptr = pattern;    /* "value" gets the RE */
140   return OK;
141   }
142
143 /* Tail match */
144
145 if (pattern[0] == '*')
146   {
147   int slen = Ustrlen(s);
148   int patlen;    /* Sun compiler doesn't like non-constant initializer */
149
150   patlen = Ustrlen(++pattern);
151   if (patlen > slen) return FAIL;
152   if (cb->flags & MCS_CASELESS
153       ? strncmpic(s + slen - patlen, pattern, patlen) != 0
154       : Ustrncmp(s + slen - patlen, pattern, patlen) != 0)
155     return FAIL;
156   if (expand_setup >= 0)
157     {
158     expand_nstring[++expand_setup] = s;         /* write a $n, the matched subject variable-part */
159     expand_nlength[expand_setup] = slen - patlen;
160     expand_nmax = expand_setup;                 /* commit also $0, the matched subject */
161     }
162   if (valueptr) *valueptr = pattern - 1;        /* "value" gets the (original) pattern */
163   return OK;
164   }
165
166 /* Match a special item starting with @ if so enabled. On its own, "@" matches
167 the primary host name - implement this by changing the pattern. For the other
168 cases we have to do some more work. If we don't recognize a special pattern,
169 just fall through - the match will fail. */
170
171 if (cb->flags & MCS_AT_SPECIAL && pattern[0] == '@')
172   {
173   if (pattern[1] == 0)
174     {
175     pattern = primary_hostname;
176     goto NOT_AT_SPECIAL;               /* Handle as exact string match */
177     }
178
179   if (Ustrcmp(pattern, "@[]") == 0)
180     {
181     int slen = Ustrlen(s);
182     if (s[0] != '[' && s[slen-1] != ']') return FAIL;           /*XXX should this be || ? */
183     for (ip_address_item * ip = host_find_interfaces(); ip; ip = ip->next)
184       if (Ustrncmp(ip->address, s+1, slen - 2) == 0
185             && ip->address[slen - 2] == 0)
186         {
187         if (expand_setup >= 0) expand_nmax = expand_setup;      /* commit $0, the IP addr */
188         if (valueptr) *valueptr = pattern;      /* "value" gets the pattern */
189         return OK;
190         }
191     return FAIL;
192     }
193
194   if (strncmpic(pattern, US"@mx_", 4) == 0)
195     {
196     int rc;
197     host_item h;
198     BOOL prim = FALSE, secy = FALSE, removed = FALSE;
199     const uschar *ss = pattern + 4;
200     const uschar *ignore_target_hosts = NULL;
201
202     if (strncmpic(ss, US"any", 3) == 0)
203       ss += 3;
204     else if (strncmpic(ss, US"primary", 7) == 0)
205       { ss += 7; prim = TRUE; }
206     else if (strncmpic(ss, US"secondary", 9) == 0)
207       { ss += 9; secy = TRUE; }
208     else
209       goto NOT_AT_SPECIAL;
210
211     if (strncmpic(ss, US"/ignore=", 8) == 0)
212       ignore_target_hosts = ss + 8;
213     else if (*ss)
214       goto NOT_AT_SPECIAL;
215
216     h.next = NULL;
217     h.name = s;
218     h.address = NULL;
219
220     rc = host_find_bydns(&h,
221       ignore_target_hosts,
222       HOST_FIND_BY_MX,     /* search only for MX, not SRV or A */
223       NULL,                /* service name not relevant */
224       NULL,                /* srv_fail_domains not relevant */
225       NULL,                /* mx_fail_domains not relevant */
226       NULL,                /* no dnssec request/require XXX ? */
227       NULL,                /* no feedback FQDN */
228       &removed);           /* feedback if local removed */
229
230     if (rc == HOST_FIND_AGAIN)
231       {
232       search_error_message = string_sprintf("DNS lookup of \"%s\" deferred", s);
233       return DEFER;
234       }
235
236     if ((rc != HOST_FOUND_LOCAL || secy) && (prim || !removed))
237       return FAIL;
238
239     if (expand_setup >= 0) expand_nmax = expand_setup;  /* commit $0, the matched subject */
240     if (valueptr) *valueptr = pattern;  /* "value" gets the patterm */
241     return OK;
242
243     /*** The above line used to be the following line, but this is incorrect,
244     because host_find_bydns() may return HOST_NOT_FOUND if it removed some MX
245     hosts, but the remaining ones were non-existent. All we are interested in
246     is whether or not it removed some hosts.
247
248     return (rc == HOST_FOUND && removed)? OK : FAIL;
249     ***/
250     }
251   }
252
253 /* Escape point from code for specials that start with "@" */
254
255 NOT_AT_SPECIAL:
256
257 /* This is an exact string match if there is no semicolon in the pattern. */
258
259 if ((semicolon = Ustrchr(pattern, ';')) == NULL)
260   {
261   if (cb->flags & MCS_CASELESS ? strcmpic(s, pattern) != 0 : Ustrcmp(s, pattern) != 0)
262     return FAIL;
263   if (expand_setup >= 0) expand_nmax = expand_setup;    /* $0 gets the matched subject */
264   if (valueptr) *valueptr = pattern;                    /* "value" gets the pattern */
265   return OK;
266   }
267
268 /* Otherwise we have a lookup item. The lookup type, including partial, etc. is
269 the part of the string preceding the semicolon. */
270
271 *semicolon = 0;
272 li = search_findtype_partial(pattern, &partial, &affix, &affixlen,
273   &starflags, &opts);
274 *semicolon = ';';
275 if (!li)
276   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", search_error_message);
277
278 /* Partial matching is not appropriate for certain lookups (e.g. when looking
279 up user@domain for sender rejection). There's a flag to disable it. */
280
281 if (!(cb->flags & MCS_PARTIAL)) partial = -1;
282
283 /* Set the parameters for the three different kinds of lookup. */
284
285 keyquery = search_args(li, s, semicolon+1, &filename, opts);
286
287 /* Now do the actual lookup; throw away the data returned unless it was asked
288 for; partial matching is all handled inside search_find(). Note that there is
289 no search_close() because of the caching arrangements. */
290
291 if (!(handle = search_open(filename, li, 0, NULL, NULL)))
292   log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", search_error_message);
293 result = search_find(handle, filename, keyquery, partial, affix, affixlen,
294   starflags, &expand_setup, opts);
295
296 if (!result) return f.search_find_defer ? DEFER : FAIL;
297 if (valueptr) *valueptr = result;
298
299 expand_nmax = expand_setup;
300 return OK;
301 }
302
303
304
305 /*************************************************
306 *      Public interface to check_string()        *
307 *************************************************/
308
309 /* This function is called from several places where is it most convenient to
310 pass the arguments individually. It places them in a check_string_block
311 structure, and then calls check_string().
312
313 Arguments:
314   s            the subject string to be checked
315   pattern      the pattern to check it against
316   expand_setup expansion setup option (see check_string())
317   flags
318    use_partial  if FALSE, override any partial- search types
319    caseless     TRUE for caseless matching where possible
320    at_is_special TRUE to recognize @, @[], etc.
321   valueptr     if not NULL, and a file lookup was done, return the result
322                  here instead of discarding it; else set it to point to NULL
323
324 Returns:       OK    if matched
325                FAIL  if not matched
326                DEFER if lookup deferred
327 */
328
329 int
330 match_check_string(const uschar * s, const uschar * pattern, int expand_setup,
331   mcs_flags flags, const uschar ** valueptr)
332 {
333 check_string_block cb;
334 cb.origsubject = s;
335 cb.subject = flags & MCS_CASELESS ? string_copylc(s) : string_copy(s);
336 cb.expand_setup = expand_setup;
337 cb.flags = flags;
338 return check_string(&cb, pattern, valueptr, NULL);
339 }
340
341
342
343 /*************************************************
344 *       Get key string from check block          *
345 *************************************************/
346
347 /* When caching the data from a lookup for a named list, we have to save the
348 key that was found, because other lookups of different keys on the same list
349 may occur. This function has knowledge of the different lookup types, and
350 extracts the appropriate key.
351
352 Arguments:
353   arg          the check block
354   type         MCL_STRING, MCL_DOMAIN, MCL_HOST, MCL_ADDRESS, or MCL_LOCALPART
355 */
356
357 static const uschar *
358 get_check_key(void *arg, int type)
359 {
360 switch(type)
361   {
362   case MCL_STRING:
363   case MCL_DOMAIN:
364   case MCL_LOCALPART:   return ((check_string_block *)arg)->subject;
365   case MCL_HOST:        return ((check_host_block *)arg)->host_address;
366   case MCL_ADDRESS:     return ((check_address_block *)arg)->address;
367   }
368 return US"";  /* In practice, should never happen */
369 }
370
371
372
373 /* Check for a change-of-separator specification on the head of a list.
374 Handle interpretation of backslash-char, in the same way that expansion would.
375
376 Argument:       listp   pointer to list-pointer, updated on return to
377                         next char after the spec if there is one; else unchaged
378
379 Return:         separator char, or zero for no spec
380 */
381
382 uschar
383 matchlist_parse_sep(const uschar ** listp)
384 {
385 const uschar * list = *listp;
386 if (Uskip_whitespace(&list) == '<')
387   {
388   const uschar * s = list+1;
389   uschar c = *s == '\\' ? string_interpret_escape(&s) : *s;
390   if (ispunct(c) || iscntrl(c))
391     {
392     DEBUG(D_lists)
393       {
394       uschar s[2] = {0}; *s = c;
395       debug_printf_indent("list separator: '%W'\n", s);
396       }
397     *listp = s+1;       /* next char after the change-of-separator */
398     return c;
399     }
400   }
401 return 0;
402 }
403
404 /*************************************************
405 *       Scan list and run matching function      *
406 *************************************************/
407
408 /* This function scans a list of patterns, and runs a matching function for
409 each item in the list. It is called from the functions that match domains,
410 local parts, hosts, and addresses, because its overall structure is the same in
411 all cases. However, the details of each particular match is different, so it
412 calls back to a given function do perform an actual match.
413
414 We can't quite keep the different types anonymous here because they permit
415 different special cases. A pity.
416
417 If a list item starts with !, that implies negation if the subject matches the
418 rest of the item (ignoring white space after the !). The result when the end of
419 the list is reached is FALSE unless the last item on the list is negated, in
420 which case it is TRUE. A file name in the list causes its lines to be
421 interpolated as if items in the list. An item starting with + is a named
422 sublist, obtained by searching the tree pointed to by anchorptr, with possible
423 cached match results in cache_bits.
424
425 Arguments:
426   listptr      pointer to the pointer to the list
427   sep          separator character for string_nextinlist();
428                  normally zero for a standard list;
429                  sometimes UCHAR_MAX+1 for single items;
430   anchorptr    -> tree of named items, or NULL if no named items
431   cache_ptr    pointer to pointer to cache bits for named items, or
432                  pointer to NULL if not caching; may get set NULL if an
433                  uncacheable named list is encountered
434   func         function to call back to do one test
435   arg          pointer to pass to the function; the string to be matched is
436                  in the structure it points to
437   type         MCL_STRING, MCL_DOMAIN, MCL_HOST, MCL_ADDRESS, or MCL_LOCALPART
438                  these are used for some special handling
439                MCL_NOEXPAND (whose value is greater than any of them) may
440                  be added to any value to suppress expansion of the list
441   name         string to use in debugging info
442   valueptr     where to pass back data from a lookup
443
444 Returns:       OK    if matched a non-negated item
445                OK    if hit end of list after a negated item
446                FAIL  if expansion force-failed
447                FAIL  if matched a negated item
448                FAIL  if hit end of list after a non-negated item
449                DEFER if a something deferred or expansion failed
450 */
451
452 int
453 match_check_list(const uschar * const * listptr, int sep, tree_node **anchorptr,
454   unsigned int **cache_ptr, int (*func)(void *,const uschar *,const uschar **,uschar **),
455   void *arg, int type, const uschar *name, const uschar **valueptr)
456 {
457 int yield = OK;
458 unsigned int * original_cache_bits = *cache_ptr;
459 BOOL include_unknown = FALSE, ignore_unknown = FALSE,
460       include_defer = FALSE, ignore_defer = FALSE;
461 const uschar * list;
462 uschar * ot = NULL, * sss;
463 BOOL textonly_re;
464
465 /* Save time by not scanning for the option name when we don't need it. */
466
467 HDEBUG(D_any)
468   {
469   const uschar * listname = readconf_find_option(listptr);
470   if (*listname) ot = string_sprintf("%s in %s?", name, listname);
471   }
472
473 /* If the list is empty, the answer is no. */
474
475 if (!*listptr)
476   {
477   HDEBUG(D_lists)
478     if (ot) debug_printf_indent("%s no (option unset)\n", ot);
479     else    debug_printf_indent("%s not in empty list (option unset? cannot trace name)\n", name);
480   return FAIL;
481   }
482
483 /* Expand the list before we scan it. A forced expansion gives the answer
484 "not in list"; other expansion errors cause DEFER to be returned. However,
485 if the type value is greater than or equal to than MCL_NOEXPAND, do not expand
486 the list. */
487
488 list = *listptr;
489 if (type >= MCL_NOEXPAND)
490   {
491   type -= MCL_NOEXPAND;       /* Remove the "no expand" flag */
492   textonly_re = TRUE;
493   }
494 else
495   {
496   if (sep <= 0)
497     sep = matchlist_parse_sep(&list);
498
499   /* If we are searching a domain list, and $domain is not set, set it to the
500   subject that is being sought for the duration of the expansion. */
501
502   if (type == MCL_DOMAIN && !deliver_domain)
503     {
504     check_string_block *cb = (check_string_block *)arg;
505     deliver_domain = string_copy(cb->subject);
506     list = expand_string_2(list, &textonly_re);
507     deliver_domain = NULL;
508     }
509   else
510     list = expand_string_2(list, &textonly_re);
511
512   if (!list)
513     {
514     if (f.expand_string_forcedfail)
515       {
516       HDEBUG(D_lists) debug_printf_indent("expansion of \"%s\" forced failure: "
517         "assume not in this list\n", *listptr);
518       return FAIL;
519       }
520     log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand \"%s\" while checking "
521       "a list: %s", *listptr, expand_string_message);
522     return DEFER;
523     }
524   }
525
526 /* If expansion had no effect on the list text, the list-test result can
527 be cached */
528
529 if (textonly_re) switch (type)
530   {
531   case MCL_STRING:
532   case MCL_DOMAIN:
533   case MCL_LOCALPART: ((check_string_block *)arg)->flags |= MCS_CACHEABLE; break;
534   case MCL_HOST:     ((check_host_block *)arg)->flags |= MCS_CACHEABLE; break;
535   case MCL_ADDRESS: ((check_address_block *)arg)->flags |= MCS_CACHEABLE; break;
536   }
537
538 /* For an unnamed list, use the expanded version in comments */
539 #define LIST_LIMIT_PR 2048
540
541 HDEBUG(D_any) if (!ot)
542   {     /* We failed to identify an option name, so give the list text */
543   int n, m;
544   gstring * g = string_fmt_append(NULL, "%s in \"%n%.*s%n\"",
545     name, &n, LIST_LIMIT_PR, list, &m);
546   if (m - n >= LIST_LIMIT_PR) g = string_catn(g, US"...", 3);
547   g = string_catn(g, US"?", 1);
548   gstring_release_unused(g);
549   ot = string_from_gstring(g);
550   }
551 HDEBUG(D_lists)
552   {
553   debug_printf_indent("%s\n", ot);
554   expand_level++;
555   }
556
557 /* Now scan the list and process each item in turn, until one of them matches,
558 or we hit an error. */
559
560 while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
561   {
562   uschar * ss = sss;
563
564   HDEBUG(D_lists) debug_printf_indent("list element: %W\n", ss);
565
566   /* Address lists may contain +caseful, to restore caseful matching of the
567   local part. We have to know the layout of the control block, unfortunately.
568   The lower cased address is in a temporary buffer, so we just copy the local
569   part back to the start of it (if a local part exists). */
570
571   if (type == MCL_ADDRESS)
572     {
573     if (Ustrcmp(ss, "+caseful") == 0)
574       {
575       check_address_block *cb = (check_address_block *)arg;
576       uschar *at = Ustrrchr(cb->origaddress, '@');
577
578       if (at)
579         Ustrncpy(cb->address, cb->origaddress, at - cb->origaddress);
580       cb->flags &= ~MCS_CASELESS;
581       continue;
582       }
583     }
584
585   /* Similar processing for local parts */
586
587   else if (type == MCL_LOCALPART)
588     {
589     if (Ustrcmp(ss, "+caseful") == 0)
590       {
591       check_string_block *cb = (check_string_block *)arg;
592       Ustrcpy(US cb->subject, cb->origsubject);
593       cb->flags &= ~MCS_CASELESS;
594       continue;
595       }
596     }
597
598   /* If the host item is "+include_unknown" or "+ignore_unknown", remember it
599   in case there's a subsequent failed reverse lookup. There is similar
600   processing for "defer". */
601
602   else if (type == MCL_HOST && *ss == '+')
603     {
604     if (Ustrcmp(ss, "+include_unknown") == 0)
605       {
606       include_unknown = TRUE;
607       ignore_unknown = FALSE;
608       continue;
609       }
610     if (Ustrcmp(ss, "+ignore_unknown") == 0)
611       {
612       ignore_unknown = TRUE;
613       include_unknown = FALSE;
614       continue;
615       }
616     if (Ustrcmp(ss, "+include_defer") == 0)
617       {
618       include_defer = TRUE;
619       ignore_defer = FALSE;
620       continue;
621       }
622     if (Ustrcmp(ss, "+ignore_defer") == 0)
623       {
624       ignore_defer = TRUE;
625       include_defer = FALSE;
626       continue;
627       }
628     }
629
630   /* Starting with ! specifies a negative item. It is theoretically possible
631   for a local part to start with !. In that case, a regex has to be used. */
632
633   if (*ss == '!')
634     {
635     yield = FAIL;
636     while (isspace(*++ss)) ;
637     }
638   else
639     yield = OK;
640
641   /* If the item is a file name, we read the file and do a match attempt
642   on each line in the file, including possibly more negation processing. */
643
644   if (*ss == '/')
645     {
646     int file_yield = yield;       /* In case empty file */
647     uschar * filename = ss;
648     FILE * f = Ufopen(filename, "rb");
649     uschar filebuffer[1024];
650
651     /* ot will be null in non-debugging cases, and anyway, we get better
652     wording by reworking it. */
653
654     if (!f)
655       {
656       const uschar * listname = readconf_find_option(listptr);
657       if (!*listname)
658         listname = string_sprintf("\"%s\"", *listptr);
659       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
660         string_open_failed("%s when checking %s", sss, listname));
661       }
662
663     /* Trailing comments are introduced by #, but in an address list or local
664     part list, the # must be preceded by white space or the start of the line,
665     because the # character is a legal character in local parts. */
666
667     while (Ufgets(filebuffer, sizeof(filebuffer), f) != NULL)
668       {
669       uschar * error, * sss = filebuffer;
670
671       while ((ss = Ustrchr(sss, '#')) != NULL)
672         {
673         if ((type != MCL_ADDRESS && type != MCL_LOCALPART) ||
674               ss == filebuffer || isspace(ss[-1]))
675           {
676           *ss = '\0';
677           break;
678           }
679         sss = ss + 1;
680         }
681
682       ss = filebuffer + Ustrlen(filebuffer);            /* trailing space */
683       while (ss > filebuffer && isspace(ss[-1])) ss--;
684       *ss = '\0';
685
686       ss = filebuffer;
687       if (!Uskip_whitespace(&ss))                       /* leading space */
688         continue;                                       /* ignore empty */
689
690       file_yield = yield;                               /* positive yield */
691       sss = ss;                                         /* for debugging */
692
693       if (*ss == '!')                                   /* negation */
694         {
695         file_yield = file_yield == OK ? FAIL : OK;
696         while (isspace(*++ss)) ;
697         }
698
699       switch ((func)(arg, ss, valueptr, &error))
700         {
701         case OK:
702           (void)fclose(f);
703           HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\" in %s)\n",
704             ot, yield == OK ? "yes" : "no", sss, filename);
705
706           /* The "pattern" being matched came from the file; we use a stack-local.
707           Copy it to allocated memory now we know it matched. */
708
709           if (valueptr) *valueptr = string_copy(ss);
710           yield = file_yield;
711           goto YIELD_RETURN;
712
713         case DEFER:
714           if (!error)
715             error = string_sprintf("DNS lookup of %s deferred", ss);
716           if (ignore_defer)
717             {
718             HDEBUG(D_lists)
719               debug_printf_indent("%s: item ignored by +ignore_defer\n", error);
720             break;
721             }
722           (void)fclose(f);
723           if (!include_defer)
724             goto DEFER_RETURN;
725           log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
726           goto OK_RETURN;
727
728         /* The ERROR return occurs when checking hosts, when either a forward
729         or reverse lookup has failed. It can also occur in a match_ip list if a
730         non-IP address item is encountered. The error string gives details of
731         which it was. */
732
733         case ERROR:
734           if (ignore_unknown)
735             {
736             HDEBUG(D_lists) debug_printf_indent(
737               "%s: item ignored by +ignore_unknown\n", error);
738             }
739           else
740             {
741             HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot,
742               include_unknown ? "yes":"no", error);
743             (void)fclose(f);
744             if (!include_unknown)
745               {
746               if (LOGGING(unknown_in_list))
747                 log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
748               goto FAIL_RETURN;
749               }
750             log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
751             goto OK_RETURN;
752             }
753         }
754       }
755
756     /* At the end of the file, leave the yield setting at the final setting
757     for the file, in case this is the last item in the list. */
758
759     yield = file_yield;
760     (void)fclose(f);
761     }
762
763   /* If the item does not begin with '/', it might be a + item for a named
764   list. Otherwise, it is just a single list entry that has to be matched.
765   We recognize '+' only when supplied with a tree of named lists. */
766
767   else if (*ss == '+' && anchorptr)
768     {
769     int bits = 0, offset = 0, shift = 0;
770     unsigned int * use_cache_bits = original_cache_bits;
771     uschar * cached = US"";
772     namedlist_block * nb;
773     tree_node * t;
774
775     HDEBUG(D_lists)
776       { debug_printf_indent(" start sublist %s\n", ss+1); expand_level += 2; }
777
778     if (!(t = tree_search(*anchorptr, ss+1)))
779       {
780       log_write(0, LOG_MAIN|LOG_PANIC, "unknown named%s list \"%s\"",
781         type == MCL_DOMAIN ?    " domain" :
782         type == MCL_HOST ?      " host" :
783         type == MCL_ADDRESS ?   " address" :
784         type == MCL_LOCALPART ? " local part" : "",
785         ss);
786       goto DEFER_RETURN;
787       }
788     nb = t->data.ptr;
789
790     /* If the list number is negative, it means that this list is not
791     cacheable because it contains expansion items. */
792
793     if (nb->number < 0) use_cache_bits = NULL;
794
795     /* If we have got a cache pointer, get the bits. This is not an "else"
796     because the pointer may be NULL from the start if caching is not
797     required. */
798
799     if (use_cache_bits)
800       {
801       offset = (nb->number)/16;
802       shift = ((nb->number)%16)*2;
803       bits = use_cache_bits[offset] & (3 << shift);
804       }
805
806     /* Not previously tested or no cache - run the full test */
807
808     if (bits == 0)
809       {
810       int res = match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits,
811               func, arg, type, name, valueptr);
812       HDEBUG(D_lists)
813         { expand_level -= 2; debug_printf_indent(" end sublist %s\n", ss+1); }
814
815       switch (res)
816         {
817         case OK:   bits = 1; break;
818         case FAIL: bits = 3; break;
819         case DEFER: goto DEFER_RETURN;
820         }
821
822       /* If this list was uncacheable, or a sublist turned out to be
823       uncacheable, the value of use_cache_bits will now be NULL, even if it
824       wasn't before. Ensure that this is passed up to the next level.
825       Otherwise, remember the result of the search in the cache. */
826
827       if (!use_cache_bits)
828         *cache_ptr = NULL;
829       else
830         {
831         use_cache_bits[offset] |= bits << shift;
832
833         if (valueptr)
834           {
835           int old_pool = store_pool;
836           namedlist_cacheblock *p;
837
838           /* Cached data for hosts persists over more than one message,
839           so we use the permanent store pool */
840
841           store_pool = POOL_PERM;
842           p = store_get(sizeof(namedlist_cacheblock), GET_UNTAINTED);
843           p->key = string_copy(get_check_key(arg, type));
844
845
846           p->data = *valueptr ? string_copy(*valueptr) : NULL;
847           store_pool = old_pool;
848
849           p->next = nb->cache_data;
850           nb->cache_data = p;
851           if (*valueptr)
852             HDEBUG(D_lists) debug_printf_indent("data from lookup saved for "
853               "cache for %s: key '%s' value '%s'\n", ss, p->key, *valueptr);
854           }
855         }
856       }
857
858      /* Previously cached; to find a lookup value, search a chain of values
859      and compare keys. Typically, there is only one such, but it is possible
860      for different keys to have matched the same named list. */
861
862     else
863       {
864       HDEBUG(D_lists)
865         {
866         expand_level -= 2;
867         debug_printf_indent("cached %s match for %s\n",
868           (bits & (-bits)) == bits ? "yes" : "no", ss);
869         }
870
871       cached = US" - cached";
872       if (valueptr)
873         {
874         const uschar *key = get_check_key(arg, type);
875
876         for (namedlist_cacheblock * p = nb->cache_data; p; p = p->next)
877           if (Ustrcmp(key, p->key) == 0)
878             {
879             *valueptr = p->data;
880             break;
881             }
882         HDEBUG(D_lists) debug_printf_indent("cached lookup data = %s\n", *valueptr);
883         }
884       }
885
886     /* Result of test is indicated by value in bits. For each test, we
887     have 00 => untested, 01 => tested yes, 11 => tested no. */
888
889     if ((bits & (-bits)) == bits)    /* Only one of the two bits is set */
890       {
891       HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\"%s)\n", ot,
892         yield == OK ? "yes" : "no", sss, cached);
893       goto YIELD_RETURN;
894       }
895     }
896
897   /* Run the provided function to do the individual test. */
898
899   else
900     {
901     uschar * error = NULL;
902     switch ((func)(arg, ss, valueptr, &error))
903       {
904       case OK:
905         HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\")\n", ot,
906           yield == OK ? "yes" : "no", sss);
907         goto YIELD_RETURN;
908
909       case DEFER:
910         if (!error)
911           error = string_sprintf("DNS lookup of \"%s\" deferred", ss);
912         if (ignore_defer)
913           {
914           HDEBUG(D_lists)
915             debug_printf_indent("%s: item ignored by +ignore_defer\n", error);
916           break;
917           }
918         if (include_defer)
919           {
920           log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
921           return OK;
922           }
923         if (!search_error_message) search_error_message = error;
924         goto DEFER_RETURN;
925
926       /* The ERROR return occurs when checking hosts, when either a forward
927       or reverse lookup has failed. It can also occur in a match_ip list if a
928       non-IP address item is encountered. The error string gives details of
929       which it was. */
930
931       case ERROR:
932         if (ignore_unknown)
933           {
934           HDEBUG(D_lists) debug_printf_indent(
935             "%s: item ignored by +ignore_unknown\n", error);
936           }
937         else
938           {
939           HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot,
940             include_unknown? "yes":"no", error);
941           if (!include_unknown)
942             {
943             if (LOGGING(unknown_in_list))
944               log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
945             return FAIL;
946             }
947           log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
948           return OK;
949           }
950       }
951     }
952
953   }    /* Loop for the next item on the top-level list */
954
955 /* End of list reached: if the last item was negated yield OK, else FAIL. */
956
957 HDEBUG(D_any)
958   {
959   HDEBUG(D_lists) expand_level--;
960   debug_printf_indent("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
961   }
962 return yield == OK ? FAIL : OK;
963  
964 /* Something deferred */
965
966 DEFER_RETURN:
967   HDEBUG(D_any)
968     {
969     HDEBUG(D_lists) expand_level--;
970     debug_printf_indent("%s list match deferred for %s\n", ot, sss);
971     }
972   return DEFER;
973
974 FAIL_RETURN:
975   yield = FAIL;
976   goto YIELD_RETURN;
977
978 OK_RETURN:
979   yield = OK;
980
981 YIELD_RETURN:
982   HDEBUG(D_lists) expand_level--;
983   return yield;
984 }
985
986
987 /*************************************************
988 *          Match in colon-separated list         *
989 *************************************************/
990
991 /* This function is used for domain lists and local part lists. It is not used
992 for host lists or address lists, which have additional interpretation of the
993 patterns. Some calls of it set sep > UCHAR_MAX in order to use its matching
994 facilities on single items. When this is done, it arranges to set the numerical
995 variables as a result of the match.
996
997 This function is now just a short interface to match_check_list(), which does
998 list scanning in a general way. A good compiler will optimize the tail
999 recursion.
1000
1001 Arguments:
1002   s              string to search for
1003   listptr        ptr to ptr to colon separated list of patterns, or NULL
1004   sep            a separator value for the list (see string_nextinlist())
1005                  or zero for auto
1006   anchorptr      ptr to tree for named items, or NULL if no named items
1007   cache_bits     ptr to cache_bits for ditto, or NULL if not caching
1008   type           MCL_DOMAIN when matching a domain list
1009                  MCL_LOCALPART when matching a local part list (address lists
1010                    have their own function)
1011                  MCL_STRING for others (e.g. list of ciphers)
1012                  MCL_NOEXPAND (whose value is greater than any of them) may
1013                    be added to any value to suppress expansion of the list
1014   caseless       TRUE for (mostly) caseless matching - passed directly to
1015                    match_check_string()
1016   valueptr       pointer to where any lookup data is to be passed back,
1017                  or NULL (just passed on to match_check_string)
1018
1019 Returns:         OK    if matched a non-negated item
1020                  OK    if hit end of list after a negated item
1021                  FAIL  if expansion force-failed
1022                  FAIL  if matched a negated item
1023                  FAIL  if hit end of list after a non-negated item
1024                  DEFER if a lookup deferred
1025 */
1026
1027 int
1028 match_isinlist(const uschar * s, const uschar * const * listptr, int sep,
1029    tree_node **anchorptr,
1030   unsigned int *cache_bits, int type, BOOL caseless, const uschar **valueptr)
1031 {
1032 unsigned int *local_cache_bits = cache_bits;
1033 check_string_block cb;
1034 cb.origsubject = s;
1035 cb.subject = caseless ? string_copylc(s) : string_copy(s);
1036 cb.flags = caseless ? MCS_PARTIAL+MCS_CASELESS : MCS_PARTIAL;
1037 switch (type & ~MCL_NOEXPAND)
1038   {
1039   case MCL_DOMAIN:      cb.flags |= MCS_AT_SPECIAL;     /*FALLTHROUGH*/
1040   case MCL_LOCALPART:   cb.expand_setup = 0;                            break;
1041   default:              cb.expand_setup = sep > UCHAR_MAX ? 0 : -1;     break;
1042   }
1043 if (valueptr) *valueptr = NULL;
1044 return  match_check_list(listptr, sep, anchorptr, &local_cache_bits,
1045   check_string, &cb, type, s, valueptr);
1046 }
1047
1048
1049
1050 /*************************************************
1051 *    Match address to single address-list item   *
1052 *************************************************/
1053
1054 /* This function matches an address to an item from an address list. It is
1055 called from match_address_list() via match_check_list(). That is why most of
1056 its arguments are in an indirect block.
1057
1058 Arguments:
1059   arg            the argument block (see below)
1060   pattern        the pattern to match
1061   valueptr       where to return a value
1062   error          for error messages (not used in this function; it never
1063                    returns ERROR)
1064
1065 The argument block contains:
1066   address        the start of the subject address; when called from retry.c
1067                    it may be *@domain if the local part isn't relevant
1068   origaddress    the original, un-case-forced address (not used here, but used
1069                    in match_check_list() when +caseful is encountered)
1070   expand_setup   controls setting up of $n variables
1071   caseless       TRUE for caseless local part matching
1072
1073 Returns:         OK     for a match
1074                  FAIL   for no match
1075                  DEFER  if a lookup deferred
1076 */
1077
1078 static int
1079 check_address(void * arg, const uschar * pattern, const uschar ** valueptr,
1080   uschar ** error)
1081 {
1082 check_address_block * cb = (check_address_block *)arg;
1083 check_string_block csb;
1084 int rc;
1085 int expand_inc = 0;
1086 unsigned int * null = NULL;
1087 const uschar * listptr;
1088 uschar * subject = cb->address;
1089 const uschar * s;
1090 uschar * pdomain, * sdomain;
1091 uschar * value = NULL;
1092
1093 DEBUG(D_lists) debug_printf_indent("address match test: subject=%s pattern=%s\n",
1094   subject, pattern);
1095
1096 /* Find the subject's domain */
1097
1098 sdomain = Ustrrchr(subject, '@');
1099
1100 /* The only case where a subject may not have a domain is if the subject is
1101 empty. Otherwise, a subject with no domain is a serious configuration error. */
1102
1103 if (!sdomain && *subject)
1104   {
1105   log_write(0, LOG_MAIN|LOG_PANIC, "no @ found in the subject of an "
1106     "address list match: subject=\"%s\" pattern=\"%s\"", subject, pattern);
1107   return FAIL;
1108   }
1109
1110 /* Handle a regular expression, which must match the entire incoming address.
1111 This may be the empty address. */
1112
1113 if (*pattern == '^')
1114   return match_check_string(subject, pattern, cb->expand_setup,
1115             cb->flags | MCS_PARTIAL, NULL);
1116
1117 /* Handle a pattern that is just a lookup. Skip over possible lookup names
1118 (letters, digits, hyphens). Skip over a possible * or *@ at the end. Then we
1119 must have a semicolon for it to be a lookup. */
1120
1121 for (s = pattern; isalnum(*s) || *s == '-'; s++) ;
1122 if (*s == '*') s++;
1123 if (*s == '@') s++;
1124
1125 /* If it is a straight lookup, do a lookup for the whole address. This may be
1126 the empty address. Partial matching doesn't make sense here, so we ignore it,
1127 but write a panic log entry. However, *@ matching will be honoured. */
1128
1129 if (*s == ';')
1130   {
1131   if (Ustrncmp(pattern, "partial-", 8) == 0)
1132     log_write(0, LOG_MAIN|LOG_PANIC, "partial matching is not applicable to "
1133       "whole-address lookups: ignored \"partial-\" in \"%s\"", pattern);
1134   return match_check_string(subject, pattern, -1, cb->flags, valueptr);
1135   }
1136
1137 /* For the remaining cases, an empty subject matches only an empty pattern,
1138 because other patterns expect to have a local part and a domain to match
1139 against. */
1140
1141 if (!*subject) return *pattern ? FAIL : OK;
1142
1143 /* If the pattern starts with "@@" we have a split lookup, where the domain is
1144 looked up to obtain a list of local parts. If the subject's local part is just
1145 "*" (called from retry) the match always fails. */
1146
1147 if (pattern[0] == '@' && pattern[1] == '@')
1148   {
1149   int watchdog = 50;
1150   uschar *list, *ss;
1151
1152   if (sdomain == subject + 1 && *subject == '*') return FAIL;
1153
1154   /* Loop for handling chains. The last item in any list may be of the form
1155   ">name" in order to chain on to another list. */
1156
1157   for (const uschar * key = sdomain + 1; key && watchdog-- > 0; )
1158     {
1159     int sep = 0;
1160
1161     if ((rc = match_check_string(key, pattern + 2, -1, MCS_PARTIAL, CUSS &list))
1162         != OK)
1163       return rc;
1164
1165     /* Check for chaining from the last item; set up the next key if one
1166     is found. */
1167
1168     ss = Ustrrchr(list, ':');
1169     if (!ss) ss = list; else ss++;
1170     if (Uskip_whitespace(&ss) == '>')
1171       {
1172       *ss++ = 0;
1173       Uskip_whitespace(&ss);
1174       key = string_copy(ss);
1175       }
1176     else key = NULL;
1177
1178     /* Look up the local parts provided by the list; negation is permitted.
1179     If a local part has to begin with !, a regex can be used. */
1180
1181     while ((ss = string_nextinlist(CUSS &list, &sep, NULL, 0)))
1182       {
1183       int local_yield;
1184
1185       if (*ss == '!')
1186         {
1187         local_yield = FAIL;
1188         while (isspace(*++ss)) ;
1189         }
1190       else local_yield = OK;
1191
1192       *sdomain = 0;
1193       rc = match_check_string(subject, ss, -1, cb->flags + MCS_PARTIAL, valueptr);
1194       *sdomain = '@';
1195
1196       switch(rc)
1197         {
1198         case OK:
1199         return local_yield;
1200
1201         case DEFER:
1202         return DEFER;
1203         }
1204       }
1205     }
1206
1207   /* End of chain loop; panic if too many times */
1208
1209   if (watchdog <= 0)
1210     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Loop detected in lookup of "
1211       "local part of %s in %s", subject, pattern);
1212
1213   /* Otherwise the local part check has failed, so the whole match
1214   fails. */
1215
1216   return FAIL;
1217   }
1218
1219
1220 /* We get here if the pattern is not a lookup or a regular expression. If it
1221 contains an @ there is both a local part and a domain. */
1222
1223 if ((pdomain = Ustrrchr(pattern, '@')))
1224   {
1225   int pllen, sllen;
1226
1227   /* If the domain in the pattern is empty or one of the special cases [] or
1228   mx_{any,primary,secondary}, and the local part in the pattern ends in "@",
1229   we have a pattern of the form <something>@@, <something>@@[], or
1230   <something>@@mx_{any,primary,secondary}. These magic "domains" are
1231   automatically interpreted in match_check_string. We just need to arrange that
1232   the leading @ is included in the domain. */
1233
1234   if (pdomain > pattern && pdomain[-1] == '@'
1235      && (pdomain[1] == 0
1236         || Ustrcmp(pdomain+1, "[]") == 0
1237         || Ustrcmp(pdomain+1, "mx_any") == 0
1238         || Ustrcmp(pdomain+1, "mx_primary") == 0
1239         || Ustrcmp(pdomain+1, "mx_secondary") == 0))
1240     pdomain--;
1241
1242   pllen = pdomain - pattern;
1243   sllen = sdomain - subject;
1244
1245   /* Compare the local parts in the subject and the pattern */
1246
1247   if (*pattern == '*')
1248     {
1249     int cllen = pllen - 1;
1250     if (sllen < cllen) return FAIL;
1251     if (cb->flags & MCS_CASELESS
1252         ? strncmpic(subject+sllen-cllen, pattern + 1, cllen) != 0
1253         : Ustrncmp(subject+sllen-cllen, pattern + 1, cllen) != 0)
1254         return FAIL;
1255     if (cb->expand_setup > 0)
1256       {
1257       expand_nstring[cb->expand_setup] = subject;
1258       expand_nlength[cb->expand_setup] = sllen - cllen;
1259       expand_inc = 1;
1260       }
1261     value = string_copyn(pattern + 1, cllen);
1262     }
1263   else
1264     {
1265     if (sllen != pllen) return FAIL;
1266     if (cb->flags & MCS_CASELESS
1267         ? strncmpic(subject, pattern, sllen) != 0
1268         : Ustrncmp(subject, pattern, sllen) != 0) return FAIL;
1269     }
1270     value = string_copyn(pattern, sllen);
1271   }
1272
1273 /* If the local part matched, or was not being checked, check the domain using
1274 the generalized function, which supports file lookups (which may defer). The
1275 original code read as follows:
1276
1277   return match_check_string(sdomain + 1,
1278       pdomain ? pdomain + 1 : pattern,
1279       cb->expand_setup + expand_inc, cb->flags, NULL);
1280
1281 This supported only literal domains and *.x.y patterns. In order to allow for
1282 named domain lists (so that you can write, for example, "senders=+xxxx"), it
1283 was changed to use the list scanning function. */
1284
1285 csb.origsubject = sdomain + 1;
1286 csb.subject = cb->flags & MCS_CASELESS
1287   ? string_copylc(sdomain+1) : string_copy(sdomain+1);
1288 csb.expand_setup = cb->expand_setup + expand_inc;
1289 csb.flags = MCS_PARTIAL | MCS_AT_SPECIAL | cb->flags & MCS_CASELESS;
1290
1291 listptr = pdomain ? pdomain + 1 : pattern;
1292 if (valueptr) *valueptr = NULL;
1293
1294   {
1295   const uschar * dvalue = NULL;
1296   rc = match_check_list(
1297     &listptr,                  /* list of one item */
1298     UCHAR_MAX+1,               /* impossible separator; single item */
1299     &domainlist_anchor,        /* it's a domain list */
1300     &null,                     /* ptr to NULL means no caching */
1301     check_string,              /* the function to do one test */
1302     &csb,                      /* its data */
1303     MCL_DOMAIN + MCL_NOEXPAND, /* domain list; don't expand */
1304     csb.subject,               /* string for messages */
1305     &dvalue);                       /* where to pass back lookup data */
1306   if (valueptr && (value || dvalue))
1307     *valueptr = string_sprintf("%s@%s",
1308                   value ? value : US"", dvalue ? dvalue : US"");
1309   }
1310 return rc;
1311 }
1312
1313
1314
1315
1316 /*************************************************
1317 *    Test whether address matches address list   *
1318 *************************************************/
1319
1320 /* This function is given an address and a list of things to match it against.
1321 The list may contain individual addresses, regular expressions, lookup
1322 specifications, and indirection via bare files. Negation is supported. The
1323 address to check can consist of just a domain, which will then match only
1324 domain items or items specified as *@domain.
1325
1326 Domains are always lower cased before the match. Local parts are also lower
1327 cased unless "caseless" is false. The work of actually scanning the list is
1328 done by match_check_list(), with an appropriate block of arguments and a
1329 callback to check_address(). During caseless matching, it will recognize
1330 +caseful and revert to caseful matching.
1331
1332 Arguments:
1333   address         address to test
1334   caseless        TRUE to start in caseless state
1335   expand          TRUE to allow list expansion
1336   listptr         list to check against
1337   cache_bits      points to cache bits for named address lists, or NULL
1338   expand_setup    controls setting up of $n variables - passed through
1339                   to check_address (q.v.)
1340   sep             separator character for the list;
1341                   may be 0 to get separator from the list;
1342                   may be UCHAR_MAX+1 for one-item list
1343   valueptr        where to return a lookup value, or NULL
1344
1345 Returns:          OK    for a positive match, or end list after a negation;
1346                   FAIL  for a negative match, or end list after non-negation;
1347                   DEFER if a lookup deferred
1348 */
1349
1350 int
1351 match_address_list(const uschar *address, BOOL caseless, BOOL expand,
1352   const uschar **listptr, unsigned int *cache_bits, int expand_setup, int sep,
1353   const uschar **valueptr)
1354 {
1355 check_address_block ab;
1356 unsigned int *local_cache_bits = cache_bits;
1357 int len;
1358
1359 /* RFC 2505 recommends that for spam checking, local parts should be caselessly
1360 compared. Therefore, Exim now forces the entire address into lower case here,
1361 provided that "caseless" is set. (It is FALSE for calls for matching rewriting
1362 patterns.) Otherwise just the domain is lower cases. A magic item "+caseful" in
1363 the list can be used to restore a caseful copy of the local part from the
1364 original address.
1365 Limit the subject address size to avoid mem-exhaustion attacks.  The size chosen
1366 is historical (we used to use big_buffer here). */
1367
1368 if ((len = Ustrlen(address)) > BIG_BUFFER_SIZE) len = BIG_BUFFER_SIZE;
1369 ab.address = string_copyn(address, len);
1370
1371 for (uschar * p = ab.address + len - 1; p >= ab.address; p--)
1372   {
1373   if (!caseless && *p == '@') break;
1374   *p = tolower(*p);
1375   }
1376
1377 /* If expand_setup is zero, we need to set up $0 to the whole thing, in
1378 case there is a match. Can't use the built-in facilities of match_check_string
1379 (via check_address), as we may just be calling that for part of the address
1380 (the domain). */
1381
1382 if (expand_setup == 0)
1383   {
1384   expand_nstring[0] = string_copy(address);
1385   expand_nlength[0] = Ustrlen(address);
1386   expand_setup++;
1387   }
1388
1389 /* Set up the data to be passed ultimately to check_address. */
1390
1391 ab.origaddress = address;
1392 /* ab.address is above */
1393 ab.expand_setup = expand_setup;
1394 ab.flags = caseless ? MCS_CASELESS : 0;
1395
1396 return match_check_list(listptr, sep, &addresslist_anchor, &local_cache_bits,
1397   check_address, &ab, MCL_ADDRESS + (expand ? 0 : MCL_NOEXPAND), address,
1398     valueptr);
1399 }
1400
1401 /* Simpler version of match_address_list; always caseless, expanding,
1402 no cache bits, no value-return.
1403
1404 Arguments:
1405   address         address to test
1406   listptr         list to check against
1407   sep             separator character for the list;
1408                   may be 0 to get separator from the list;
1409                   may be UCHAR_MAX+1 for one-item list
1410
1411 Returns:          OK    for a positive match, or end list after a negation;
1412                   FAIL  for a negative match, or end list after non-negation;
1413                   DEFER if a lookup deferred
1414 */
1415
1416 int
1417 match_address_list_basic(const uschar *address, const uschar **listptr, int sep)
1418 {
1419 return match_address_list(address, TRUE, TRUE, listptr, NULL, -1, sep, NULL);
1420 }
1421
1422 /* End of match.c */
1423 /* vi: aw ai sw=2
1424 */