df440108e01085c45d558e431d894418518b6846
[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;
829       uschar *sss = filebuffer;
830
831       while ((ss = Ustrchr(sss, '#')) != NULL)
832         {
833         if ((type != MCL_ADDRESS && type != MCL_LOCALPART) ||
834               ss == filebuffer || isspace(ss[-1]))
835           {
836           *ss = 0;
837           break;
838           }
839         sss = ss + 1;
840         }
841
842       ss = filebuffer + Ustrlen(filebuffer);            /* trailing space */
843       while (ss > filebuffer && isspace(ss[-1])) ss--;
844       *ss = 0;
845
846       ss = filebuffer;
847       while (isspace(*ss)) ss++;                        /* leading space */
848
849       if (!*ss) continue;                               /* ignore empty */
850
851       file_yield = yield;                               /* positive yield */
852       sss = ss;                                         /* for debugging */
853
854       if (*ss == '!')                                   /* negation */
855         {
856         file_yield = (file_yield == OK)? FAIL : OK;
857         while (isspace((*(++ss))));
858         }
859
860       switch ((func)(arg, ss, valueptr, &error))
861         {
862         case OK:
863           (void)fclose(f);
864           HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\" in %s)\n", ot,
865             yield == OK ? "yes" : "no", sss, filename);
866
867           /* The "pattern" being matched came from the file; we use a stack-local.
868           Copy it to allocated memory now we know it matched. */
869
870           if (valueptr) *valueptr = string_copy(ss);
871           yield = file_yield;
872           goto YIELD_RETURN;
873
874         case DEFER:
875           if (!error)
876             error = string_sprintf("DNS lookup of %s deferred", ss);
877           if (ignore_defer)
878             {
879             HDEBUG(D_lists) debug_printf_indent("%s: item ignored by +ignore_defer\n",
880               error);
881             break;
882             }
883           (void)fclose(f);
884           if (!include_defer)
885             goto DEFER_RETURN;
886           log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
887           goto OK_RETURN;
888
889         case ERROR:             /* host name lookup failed - this can only */
890           if (ignore_unknown)   /* be for an incoming host (not outgoing) */
891             {
892             HDEBUG(D_lists) debug_printf_indent("%s: item ignored by +ignore_unknown\n",
893               error);
894             }
895           else
896            {
897             HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot,
898               include_unknown? "yes":"no", error);
899             (void)fclose(f);
900             if (!include_unknown)
901               {
902               if (LOGGING(unknown_in_list))
903                 log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
904               goto FAIL_RETURN;
905               }
906             log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
907             goto OK_RETURN;
908             }
909         }
910       }
911
912     /* At the end of the file, leave the yield setting at the final setting
913     for the file, in case this is the last item in the list. */
914
915     yield = file_yield;
916     (void)fclose(f);
917     }
918   }    /* Loop for the next item on the top-level list */
919
920 /* End of list reached: if the last item was negated yield OK, else FAIL. */
921
922 HDEBUG(D_lists)
923   HDEBUG(D_lists)
924     {
925     expand_level--;
926     debug_printf_indent("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
927     }
928   return yield == OK ? FAIL : OK;
929
930 /* Something deferred */
931
932 DEFER_RETURN:
933   HDEBUG(D_lists)
934     {
935     expand_level--;
936     debug_printf_indent("%s list match deferred for %s\n", ot, sss);
937     }
938   return DEFER;
939
940 FAIL_RETURN:
941   yield = FAIL;
942   goto YIELD_RETURN;
943
944 OK_RETURN:
945   yield = OK;
946
947 YIELD_RETURN:
948   HDEBUG(D_lists) expand_level--;
949   return yield;
950 }
951
952
953 /*************************************************
954 *          Match in colon-separated list         *
955 *************************************************/
956
957 /* This function is used for domain lists and local part lists. It is not used
958 for host lists or address lists, which have additional interpretation of the
959 patterns. Some calls of it set sep > UCHAR_MAX in order to use its matching
960 facilities on single items. When this is done, it arranges to set the numerical
961 variables as a result of the match.
962
963 This function is now just a short interface to match_check_list(), which does
964 list scanning in a general way. A good compiler will optimize the tail
965 recursion.
966
967 Arguments:
968   s              string to search for
969   listptr        ptr to ptr to colon separated list of patterns, or NULL
970   sep            a separator value for the list (see string_nextinlist())
971                  or zero for auto
972   anchorptr      ptr to tree for named items, or NULL if no named items
973   cache_bits     ptr to cache_bits for ditto, or NULL if not caching
974   type           MCL_DOMAIN when matching a domain list
975                  MCL_LOCALPART when matching a local part list (address lists
976                    have their own function)
977                  MCL_STRING for others (e.g. list of ciphers)
978                  MCL_NOEXPAND (whose value is greater than any of them) may
979                    be added to any value to suppress expansion of the list
980   caseless       TRUE for (mostly) caseless matching - passed directly to
981                    match_check_string()
982   valueptr       pointer to where any lookup data is to be passed back,
983                  or NULL (just passed on to match_check_string)
984
985 Returns:         OK    if matched a non-negated item
986                  OK    if hit end of list after a negated item
987                  FAIL  if expansion force-failed
988                  FAIL  if matched a negated item
989                  FAIL  if hit end of list after a non-negated item
990                  DEFER if a lookup deferred
991 */
992
993 int
994 match_isinlist(const uschar *s, const uschar **listptr, int sep,
995    tree_node **anchorptr,
996   unsigned int *cache_bits, int type, BOOL caseless, const uschar **valueptr)
997 {
998 unsigned int *local_cache_bits = cache_bits;
999 check_string_block cb;
1000 cb.origsubject = s;
1001 cb.subject = caseless ? string_copylc(s) : string_copy(s);
1002 cb.flags = caseless ? MCS_PARTIAL+MCS_CASELESS : MCS_PARTIAL;
1003 switch (type & ~MCL_NOEXPAND)
1004   {
1005   case MCL_DOMAIN:      cb.flags |= MCS_AT_SPECIAL;     /*FALLTHROUGH*/
1006   case MCL_LOCALPART:   cb.expand_setup = 0;                            break;
1007   default:              cb.expand_setup = sep > UCHAR_MAX ? 0 : -1;     break;
1008   }
1009 if (valueptr) *valueptr = NULL;
1010 return  match_check_list(listptr, sep, anchorptr, &local_cache_bits,
1011   check_string, &cb, type, s, valueptr);
1012 }
1013
1014
1015
1016 /*************************************************
1017 *    Match address to single address-list item   *
1018 *************************************************/
1019
1020 /* This function matches an address to an item from an address list. It is
1021 called from match_address_list() via match_check_list(). That is why most of
1022 its arguments are in an indirect block.
1023
1024 Arguments:
1025   arg            the argument block (see below)
1026   pattern        the pattern to match
1027   valueptr       where to return a value
1028   error          for error messages (not used in this function; it never
1029                    returns ERROR)
1030
1031 The argument block contains:
1032   address        the start of the subject address; when called from retry.c
1033                    it may be *@domain if the local part isn't relevant
1034   origaddress    the original, un-case-forced address (not used here, but used
1035                    in match_check_list() when +caseful is encountered)
1036   expand_setup   controls setting up of $n variables
1037   caseless       TRUE for caseless local part matching
1038
1039 Returns:         OK     for a match
1040                  FAIL   for no match
1041                  DEFER  if a lookup deferred
1042 */
1043
1044 static int
1045 check_address(void * arg, const uschar * pattern, const uschar ** valueptr,
1046   uschar ** error)
1047 {
1048 check_address_block * cb = (check_address_block *)arg;
1049 check_string_block csb;
1050 int rc;
1051 int expand_inc = 0;
1052 unsigned int * null = NULL;
1053 const uschar * listptr;
1054 uschar * subject = cb->address;
1055 const uschar * s;
1056 uschar * pdomain, * sdomain;
1057 uschar * value = NULL;
1058
1059 DEBUG(D_lists) debug_printf_indent("address match test: subject=%s pattern=%s\n",
1060   subject, pattern);
1061
1062 /* Find the subject's domain */
1063
1064 sdomain = Ustrrchr(subject, '@');
1065
1066 /* The only case where a subject may not have a domain is if the subject is
1067 empty. Otherwise, a subject with no domain is a serious configuration error. */
1068
1069 if (!sdomain && *subject)
1070   {
1071   log_write(0, LOG_MAIN|LOG_PANIC, "no @ found in the subject of an "
1072     "address list match: subject=\"%s\" pattern=\"%s\"", subject, pattern);
1073   return FAIL;
1074   }
1075
1076 /* Handle a regular expression, which must match the entire incoming address.
1077 This may be the empty address. */
1078
1079 if (*pattern == '^')
1080   return match_check_string(subject, pattern, cb->expand_setup,
1081             cb->flags | MCS_PARTIAL, NULL);
1082
1083 /* Handle a pattern that is just a lookup. Skip over possible lookup names
1084 (letters, digits, hyphens). Skip over a possible * or *@ at the end. Then we
1085 must have a semicolon for it to be a lookup. */
1086
1087 for (s = pattern; isalnum(*s) || *s == '-'; s++) ;
1088 if (*s == '*') s++;
1089 if (*s == '@') s++;
1090
1091 /* If it is a straight lookup, do a lookup for the whole address. This may be
1092 the empty address. Partial matching doesn't make sense here, so we ignore it,
1093 but write a panic log entry. However, *@ matching will be honoured. */
1094
1095 if (*s == ';')
1096   {
1097   if (Ustrncmp(pattern, "partial-", 8) == 0)
1098     log_write(0, LOG_MAIN|LOG_PANIC, "partial matching is not applicable to "
1099       "whole-address lookups: ignored \"partial-\" in \"%s\"", pattern);
1100   return match_check_string(subject, pattern, -1, cb->flags, valueptr);
1101   }
1102
1103 /* For the remaining cases, an empty subject matches only an empty pattern,
1104 because other patterns expect to have a local part and a domain to match
1105 against. */
1106
1107 if (!*subject) return *pattern ? FAIL : OK;
1108
1109 /* If the pattern starts with "@@" we have a split lookup, where the domain is
1110 looked up to obtain a list of local parts. If the subject's local part is just
1111 "*" (called from retry) the match always fails. */
1112
1113 if (pattern[0] == '@' && pattern[1] == '@')
1114   {
1115   int watchdog = 50;
1116   uschar *list, *ss;
1117
1118   if (sdomain == subject + 1 && *subject == '*') return FAIL;
1119
1120   /* Loop for handling chains. The last item in any list may be of the form
1121   ">name" in order to chain on to another list. */
1122
1123   for (const uschar * key = sdomain + 1; key && watchdog-- > 0; )
1124     {
1125     int sep = 0;
1126
1127     if ((rc = match_check_string(key, pattern + 2, -1, MCS_PARTIAL, CUSS &list))
1128         != OK)
1129       return rc;
1130
1131     /* Check for chaining from the last item; set up the next key if one
1132     is found. */
1133
1134     ss = Ustrrchr(list, ':');
1135     if (!ss) ss = list; else ss++;
1136     Uskip_whitespace(&ss);
1137     if (*ss == '>')
1138       {
1139       *ss++ = 0;
1140       Uskip_whitespace(&ss);
1141       key = string_copy(ss);
1142       }
1143     else key = NULL;
1144
1145     /* Look up the local parts provided by the list; negation is permitted.
1146     If a local part has to begin with !, a regex can be used. */
1147
1148     while ((ss = string_nextinlist(CUSS &list, &sep, NULL, 0)))
1149       {
1150       int local_yield;
1151
1152       if (*ss == '!')
1153         {
1154         local_yield = FAIL;
1155         while (isspace((*(++ss))));
1156         }
1157       else local_yield = OK;
1158
1159       *sdomain = 0;
1160       rc = match_check_string(subject, ss, -1, cb->flags + MCS_PARTIAL, valueptr);
1161       *sdomain = '@';
1162
1163       switch(rc)
1164         {
1165         case OK:
1166         return local_yield;
1167
1168         case DEFER:
1169         return DEFER;
1170         }
1171       }
1172     }
1173
1174   /* End of chain loop; panic if too many times */
1175
1176   if (watchdog <= 0)
1177     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Loop detected in lookup of "
1178       "local part of %s in %s", subject, pattern);
1179
1180   /* Otherwise the local part check has failed, so the whole match
1181   fails. */
1182
1183   return FAIL;
1184   }
1185
1186
1187 /* We get here if the pattern is not a lookup or a regular expression. If it
1188 contains an @ there is both a local part and a domain. */
1189
1190 if ((pdomain = Ustrrchr(pattern, '@')))
1191   {
1192   int pllen, sllen;
1193
1194   /* If the domain in the pattern is empty or one of the special cases [] or
1195   mx_{any,primary,secondary}, and the local part in the pattern ends in "@",
1196   we have a pattern of the form <something>@@, <something>@@[], or
1197   <something>@@mx_{any,primary,secondary}. These magic "domains" are
1198   automatically interpreted in match_check_string. We just need to arrange that
1199   the leading @ is included in the domain. */
1200
1201   if (pdomain > pattern && pdomain[-1] == '@' &&
1202        (pdomain[1] == 0 ||
1203         Ustrcmp(pdomain+1, "[]") == 0 ||
1204         Ustrcmp(pdomain+1, "mx_any") == 0 ||
1205         Ustrcmp(pdomain+1, "mx_primary") == 0 ||
1206         Ustrcmp(pdomain+1, "mx_secondary") == 0))
1207     pdomain--;
1208
1209   pllen = pdomain - pattern;
1210   sllen = sdomain - subject;
1211
1212   /* Compare the local parts in the subject and the pattern */
1213
1214   if (*pattern == '*')
1215     {
1216     int cllen = pllen - 1;
1217     if (sllen < cllen) return FAIL;
1218     if (cb->flags & MCS_CASELESS
1219         ? strncmpic(subject+sllen-cllen, pattern + 1, cllen) != 0
1220         : Ustrncmp(subject+sllen-cllen, pattern + 1, cllen) != 0)
1221         return FAIL;
1222     if (cb->expand_setup > 0)
1223       {
1224       expand_nstring[cb->expand_setup] = subject;
1225       expand_nlength[cb->expand_setup] = sllen - cllen;
1226       expand_inc = 1;
1227       }
1228     value = string_copyn(pattern + 1, cllen);
1229     }
1230   else
1231     {
1232     if (sllen != pllen) return FAIL;
1233     if (cb->flags & MCS_CASELESS
1234         ? strncmpic(subject, pattern, sllen) != 0
1235         : Ustrncmp(subject, pattern, sllen) != 0) return FAIL;
1236     }
1237     value = string_copyn(pattern, sllen);
1238   }
1239
1240 /* If the local part matched, or was not being checked, check the domain using
1241 the generalized function, which supports file lookups (which may defer). The
1242 original code read as follows:
1243
1244   return match_check_string(sdomain + 1,
1245       pdomain ? pdomain + 1 : pattern,
1246       cb->expand_setup + expand_inc, cb->flags, NULL);
1247
1248 This supported only literal domains and *.x.y patterns. In order to allow for
1249 named domain lists (so that you can write, for example, "senders=+xxxx"), it
1250 was changed to use the list scanning function. */
1251
1252 csb.origsubject = sdomain + 1;
1253 csb.subject = cb->flags & MCS_CASELESS
1254   ? string_copylc(sdomain+1) : string_copy(sdomain+1);
1255 csb.expand_setup = cb->expand_setup + expand_inc;
1256 csb.flags = MCS_PARTIAL | MCS_AT_SPECIAL | cb->flags & MCS_CASELESS;
1257
1258 listptr = pdomain ? pdomain + 1 : pattern;
1259 if (valueptr) *valueptr = NULL;
1260
1261   {
1262   const uschar * dvalue = NULL;
1263   rc = match_check_list(
1264     &listptr,                  /* list of one item */
1265     UCHAR_MAX+1,               /* impossible separator; single item */
1266     &domainlist_anchor,        /* it's a domain list */
1267     &null,                     /* ptr to NULL means no caching */
1268     check_string,              /* the function to do one test */
1269     &csb,                      /* its data */
1270     MCL_DOMAIN + MCL_NOEXPAND, /* domain list; don't expand */
1271     csb.subject,               /* string for messages */
1272     &dvalue);                       /* where to pass back lookup data */
1273   if (valueptr && (value || dvalue))
1274     *valueptr = string_sprintf("%s@%s",
1275                   value ? value : US"", dvalue ? dvalue : US"");
1276   }
1277 return rc;
1278 }
1279
1280
1281
1282
1283 /*************************************************
1284 *    Test whether address matches address list   *
1285 *************************************************/
1286
1287 /* This function is given an address and a list of things to match it against.
1288 The list may contain individual addresses, regular expressions, lookup
1289 specifications, and indirection via bare files. Negation is supported. The
1290 address to check can consist of just a domain, which will then match only
1291 domain items or items specified as *@domain.
1292
1293 Domains are always lower cased before the match. Local parts are also lower
1294 cased unless "caseless" is false. The work of actually scanning the list is
1295 done by match_check_list(), with an appropriate block of arguments and a
1296 callback to check_address(). During caseless matching, it will recognize
1297 +caseful and revert to caseful matching.
1298
1299 Arguments:
1300   address         address to test
1301   caseless        TRUE to start in caseless state
1302   expand          TRUE to allow list expansion
1303   listptr         list to check against
1304   cache_bits      points to cache bits for named address lists, or NULL
1305   expand_setup    controls setting up of $n variables - passed through
1306                   to check_address (q.v.)
1307   sep             separator character for the list;
1308                   may be 0 to get separator from the list;
1309                   may be UCHAR_MAX+1 for one-item list
1310   valueptr        where to return a lookup value, or NULL
1311
1312 Returns:          OK    for a positive match, or end list after a negation;
1313                   FAIL  for a negative match, or end list after non-negation;
1314                   DEFER if a lookup deferred
1315 */
1316
1317 int
1318 match_address_list(const uschar *address, BOOL caseless, BOOL expand,
1319   const uschar **listptr, unsigned int *cache_bits, int expand_setup, int sep,
1320   const uschar **valueptr)
1321 {
1322 check_address_block ab;
1323 unsigned int *local_cache_bits = cache_bits;
1324 int len;
1325
1326 /* RFC 2505 recommends that for spam checking, local parts should be caselessly
1327 compared. Therefore, Exim now forces the entire address into lower case here,
1328 provided that "caseless" is set. (It is FALSE for calls for matching rewriting
1329 patterns.) Otherwise just the domain is lower cases. A magic item "+caseful" in
1330 the list can be used to restore a caseful copy of the local part from the
1331 original address.
1332 Limit the subject address size to avoid mem-exhaustion attacks.  The size chosen
1333 is historical (we used to use big_buffer here). */
1334
1335 if ((len = Ustrlen(address)) > BIG_BUFFER_SIZE) len = BIG_BUFFER_SIZE;
1336 ab.address = string_copyn(address, len);
1337
1338 for (uschar * p = ab.address + len - 1; p >= ab.address; p--)
1339   {
1340   if (!caseless && *p == '@') break;
1341   *p = tolower(*p);
1342   }
1343
1344 /* If expand_setup is zero, we need to set up $0 to the whole thing, in
1345 case there is a match. Can't use the built-in facilities of match_check_string
1346 (via check_address), as we may just be calling that for part of the address
1347 (the domain). */
1348
1349 if (expand_setup == 0)
1350   {
1351   expand_nstring[0] = string_copy(address);
1352   expand_nlength[0] = Ustrlen(address);
1353   expand_setup++;
1354   }
1355
1356 /* Set up the data to be passed ultimately to check_address. */
1357
1358 ab.origaddress = address;
1359 /* ab.address is above */
1360 ab.expand_setup = expand_setup;
1361 ab.flags = caseless ? MCS_CASELESS : 0;
1362
1363 return match_check_list(listptr, sep, &addresslist_anchor, &local_cache_bits,
1364   check_address, &ab, MCL_ADDRESS + (expand ? 0 : MCL_NOEXPAND), address,
1365     valueptr);
1366 }
1367
1368 /* Simpler version of match_address_list; always caseless, expanding,
1369 no cache bits, no value-return.
1370
1371 Arguments:
1372   address         address to test
1373   listptr         list to check against
1374   sep             separator character for the list;
1375                   may be 0 to get separator from the list;
1376                   may be UCHAR_MAX+1 for one-item list
1377
1378 Returns:          OK    for a positive match, or end list after a negation;
1379                   FAIL  for a negative match, or end list after non-negation;
1380                   DEFER if a lookup deferred
1381 */
1382
1383 int
1384 match_address_list_basic(const uschar *address, const uschar **listptr, int sep)
1385 {
1386 return match_address_list(address, TRUE, TRUE, listptr, NULL, -1, sep, NULL);
1387 }
1388
1389 /* End of match.c */