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