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