SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / expand.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
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
11 /* Functions for handling string expansion. */
12
13
14 #include "exim.h"
15
16 typedef unsigned esi_flags;
17 #define ESI_NOFLAGS             0
18 #define ESI_BRACE_ENDS          BIT(0)  /* expansion should stop at } */
19 #define ESI_HONOR_DOLLAR        BIT(1)  /* $ is meaningfull */
20 #define ESI_SKIPPING            BIT(2)  /* value will not be needed */
21
22 /* Recursively called function */
23
24 static uschar *expand_string_internal(const uschar *, esi_flags, const uschar **, BOOL *, BOOL *);
25 static int_eximarith_t expanded_string_integer(const uschar *, BOOL);
26
27 #ifdef STAND_ALONE
28 # ifndef SUPPORT_CRYPTEQ
29 #  define SUPPORT_CRYPTEQ
30 # endif
31 #endif
32
33 #ifdef LOOKUP_LDAP
34 # include "lookups/ldap.h"
35 #endif
36
37 #ifdef SUPPORT_CRYPTEQ
38 # ifdef CRYPT_H
39 #  include <crypt.h>
40 # endif
41 # ifndef HAVE_CRYPT16
42 extern char* crypt16(char*, char*);
43 # endif
44 #endif
45
46 /* The handling of crypt16() is a mess. I will record below the analysis of the
47 mess that was sent to me. We decided, however, to make changing this very low
48 priority, because in practice people are moving away from the crypt()
49 algorithms nowadays, so it doesn't seem worth it.
50
51 <quote>
52 There is an algorithm named "crypt16" in Ultrix and Tru64.  It crypts
53 the first 8 characters of the password using a 20-round version of crypt
54 (standard crypt does 25 rounds).  It then crypts the next 8 characters,
55 or an empty block if the password is less than 9 characters, using a
56 20-round version of crypt and the same salt as was used for the first
57 block.  Characters after the first 16 are ignored.  It always generates
58 a 16-byte hash, which is expressed together with the salt as a string
59 of 24 base 64 digits.  Here are some links to peruse:
60
61         http://cvs.pld.org.pl/pam/pamcrypt/crypt16.c?rev=1.2
62         http://seclists.org/bugtraq/1999/Mar/0076.html
63
64 There's a different algorithm named "bigcrypt" in HP-UX, Digital Unix,
65 and OSF/1.  This is the same as the standard crypt if given a password
66 of 8 characters or less.  If given more, it first does the same as crypt
67 using the first 8 characters, then crypts the next 8 (the 9th to 16th)
68 using as salt the first two base 64 digits from the first hash block.
69 If the password is more than 16 characters then it crypts the 17th to 24th
70 characters using as salt the first two base 64 digits from the second hash
71 block.  And so on: I've seen references to it cutting off the password at
72 40 characters (5 blocks), 80 (10 blocks), or 128 (16 blocks).  Some links:
73
74         http://cvs.pld.org.pl/pam/pamcrypt/bigcrypt.c?rev=1.2
75         http://seclists.org/bugtraq/1999/Mar/0109.html
76         http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-Q0R2D-
77              TET1_html/sec.c222.html#no_id_208
78
79 Exim has something it calls "crypt16".  It will either use a native
80 crypt16 or its own implementation.  A native crypt16 will presumably
81 be the one that I called "crypt16" above.  The internal "crypt16"
82 function, however, is a two-block-maximum implementation of what I called
83 "bigcrypt".  The documentation matches the internal code.
84
85 I suspect that whoever did the "crypt16" stuff for Exim didn't realise
86 that crypt16 and bigcrypt were different things.
87
88 Exim uses the LDAP-style scheme identifier "{crypt16}" to refer
89 to whatever it is using under that name.  This unfortunately sets a
90 precedent for using "{crypt16}" to identify two incompatible algorithms
91 whose output can't be distinguished.  With "{crypt16}" thus rendered
92 ambiguous, I suggest you deprecate it and invent two new identifiers
93 for the two algorithms.
94
95 Both crypt16 and bigcrypt are very poor algorithms, btw.  Hashing parts
96 of the password separately means they can be cracked separately, so
97 the double-length hash only doubles the cracking effort instead of
98 squaring it.  I recommend salted SHA-1 ({SSHA}), or the Blowfish-based
99 bcrypt ({CRYPT}$2a$).
100 </quote>
101 */
102
103
104
105 /*************************************************
106 *            Local statics and tables            *
107 *************************************************/
108
109 /* Table of item names, and corresponding switch numbers. The names must be in
110 alphabetical order. */
111
112 static uschar *item_table[] = {
113   US"acl",
114   US"authresults",
115   US"certextract",
116   US"dlfunc",
117   US"env",
118   US"extract",
119   US"filter",
120   US"hash",
121   US"hmac",
122   US"if",
123 #ifdef SUPPORT_I18N
124   US"imapfolder",
125 #endif
126   US"length",
127   US"listextract",
128   US"listquote",
129   US"lookup",
130   US"map",
131   US"nhash",
132   US"perl",
133   US"prvs",
134   US"prvscheck",
135   US"readfile",
136   US"readsocket",
137   US"reduce",
138   US"run",
139   US"sg",
140   US"sort",
141 #ifdef SUPPORT_SRS
142   US"srs_encode",
143 #endif
144   US"substr",
145   US"tr" };
146
147 enum {
148   EITEM_ACL,
149   EITEM_AUTHRESULTS,
150   EITEM_CERTEXTRACT,
151   EITEM_DLFUNC,
152   EITEM_ENV,
153   EITEM_EXTRACT,
154   EITEM_FILTER,
155   EITEM_HASH,
156   EITEM_HMAC,
157   EITEM_IF,
158 #ifdef SUPPORT_I18N
159   EITEM_IMAPFOLDER,
160 #endif
161   EITEM_LENGTH,
162   EITEM_LISTEXTRACT,
163   EITEM_LISTQUOTE,
164   EITEM_LOOKUP,
165   EITEM_MAP,
166   EITEM_NHASH,
167   EITEM_PERL,
168   EITEM_PRVS,
169   EITEM_PRVSCHECK,
170   EITEM_READFILE,
171   EITEM_READSOCK,
172   EITEM_REDUCE,
173   EITEM_RUN,
174   EITEM_SG,
175   EITEM_SORT,
176 #ifdef SUPPORT_SRS
177   EITEM_SRS_ENCODE,
178 #endif
179   EITEM_SUBSTR,
180   EITEM_TR };
181
182 /* Tables of operator names, and corresponding switch numbers. The names must be
183 in alphabetical order. There are two tables, because underscore is used in some
184 cases to introduce arguments, whereas for other it is part of the name. This is
185 an historical mis-design. */
186
187 static uschar * op_table_underscore[] = {
188   US"from_utf8",
189   US"local_part",
190   US"quote_local_part",
191   US"reverse_ip",
192   US"time_eval",
193   US"time_interval"
194 #ifdef SUPPORT_I18N
195  ,US"utf8_domain_from_alabel",
196   US"utf8_domain_to_alabel",
197   US"utf8_localpart_from_alabel",
198   US"utf8_localpart_to_alabel"
199 #endif
200   };
201
202 enum {
203   EOP_FROM_UTF8,
204   EOP_LOCAL_PART,
205   EOP_QUOTE_LOCAL_PART,
206   EOP_REVERSE_IP,
207   EOP_TIME_EVAL,
208   EOP_TIME_INTERVAL
209 #ifdef SUPPORT_I18N
210  ,EOP_UTF8_DOMAIN_FROM_ALABEL,
211   EOP_UTF8_DOMAIN_TO_ALABEL,
212   EOP_UTF8_LOCALPART_FROM_ALABEL,
213   EOP_UTF8_LOCALPART_TO_ALABEL
214 #endif
215   };
216
217 static uschar *op_table_main[] = {
218   US"address",
219   US"addresses",
220   US"base32",
221   US"base32d",
222   US"base62",
223   US"base62d",
224   US"base64",
225   US"base64d",
226   US"domain",
227   US"escape",
228   US"escape8bit",
229   US"eval",
230   US"eval10",
231   US"expand",
232   US"h",
233   US"hash",
234   US"hex2b64",
235   US"hexquote",
236   US"ipv6denorm",
237   US"ipv6norm",
238   US"l",
239   US"lc",
240   US"length",
241   US"listcount",
242   US"listnamed",
243   US"mask",
244   US"md5",
245   US"nh",
246   US"nhash",
247   US"quote",
248   US"randint",
249   US"rfc2047",
250   US"rfc2047d",
251   US"rxquote",
252   US"s",
253   US"sha1",
254   US"sha2",
255   US"sha256",
256   US"sha3",
257   US"stat",
258   US"str2b64",
259   US"strlen",
260   US"substr",
261   US"uc",
262   US"utf8clean" };
263
264 enum {
265   EOP_ADDRESS =  nelem(op_table_underscore),
266   EOP_ADDRESSES,
267   EOP_BASE32,
268   EOP_BASE32D,
269   EOP_BASE62,
270   EOP_BASE62D,
271   EOP_BASE64,
272   EOP_BASE64D,
273   EOP_DOMAIN,
274   EOP_ESCAPE,
275   EOP_ESCAPE8BIT,
276   EOP_EVAL,
277   EOP_EVAL10,
278   EOP_EXPAND,
279   EOP_H,
280   EOP_HASH,
281   EOP_HEX2B64,
282   EOP_HEXQUOTE,
283   EOP_IPV6DENORM,
284   EOP_IPV6NORM,
285   EOP_L,
286   EOP_LC,
287   EOP_LENGTH,
288   EOP_LISTCOUNT,
289   EOP_LISTNAMED,
290   EOP_MASK,
291   EOP_MD5,
292   EOP_NH,
293   EOP_NHASH,
294   EOP_QUOTE,
295   EOP_RANDINT,
296   EOP_RFC2047,
297   EOP_RFC2047D,
298   EOP_RXQUOTE,
299   EOP_S,
300   EOP_SHA1,
301   EOP_SHA2,
302   EOP_SHA256,
303   EOP_SHA3,
304   EOP_STAT,
305   EOP_STR2B64,
306   EOP_STRLEN,
307   EOP_SUBSTR,
308   EOP_UC,
309   EOP_UTF8CLEAN };
310
311
312 /* Table of condition names, and corresponding switch numbers. The names must
313 be in alphabetical order. */
314
315 static uschar *cond_table[] = {
316   US"<",
317   US"<=",
318   US"=",
319   US"==",     /* Backward compatibility */
320   US">",
321   US">=",
322   US"acl",
323   US"and",
324   US"bool",
325   US"bool_lax",
326   US"crypteq",
327   US"def",
328   US"eq",
329   US"eqi",
330   US"exists",
331   US"first_delivery",
332   US"forall",
333   US"forall_json",
334   US"forall_jsons",
335   US"forany",
336   US"forany_json",
337   US"forany_jsons",
338   US"ge",
339   US"gei",
340   US"gt",
341   US"gti",
342 #ifdef SUPPORT_SRS
343   US"inbound_srs",
344 #endif
345   US"inlist",
346   US"inlisti",
347   US"isip",
348   US"isip4",
349   US"isip6",
350   US"ldapauth",
351   US"le",
352   US"lei",
353   US"lt",
354   US"lti",
355   US"match",
356   US"match_address",
357   US"match_domain",
358   US"match_ip",
359   US"match_local_part",
360   US"or",
361   US"pam",
362   US"pwcheck",
363   US"queue_running",
364   US"radius",
365   US"saslauthd"
366 };
367
368 enum {
369   ECOND_NUM_L,
370   ECOND_NUM_LE,
371   ECOND_NUM_E,
372   ECOND_NUM_EE,
373   ECOND_NUM_G,
374   ECOND_NUM_GE,
375   ECOND_ACL,
376   ECOND_AND,
377   ECOND_BOOL,
378   ECOND_BOOL_LAX,
379   ECOND_CRYPTEQ,
380   ECOND_DEF,
381   ECOND_STR_EQ,
382   ECOND_STR_EQI,
383   ECOND_EXISTS,
384   ECOND_FIRST_DELIVERY,
385   ECOND_FORALL,
386   ECOND_FORALL_JSON,
387   ECOND_FORALL_JSONS,
388   ECOND_FORANY,
389   ECOND_FORANY_JSON,
390   ECOND_FORANY_JSONS,
391   ECOND_STR_GE,
392   ECOND_STR_GEI,
393   ECOND_STR_GT,
394   ECOND_STR_GTI,
395 #ifdef SUPPORT_SRS
396   ECOND_INBOUND_SRS,
397 #endif
398   ECOND_INLIST,
399   ECOND_INLISTI,
400   ECOND_ISIP,
401   ECOND_ISIP4,
402   ECOND_ISIP6,
403   ECOND_LDAPAUTH,
404   ECOND_STR_LE,
405   ECOND_STR_LEI,
406   ECOND_STR_LT,
407   ECOND_STR_LTI,
408   ECOND_MATCH,
409   ECOND_MATCH_ADDRESS,
410   ECOND_MATCH_DOMAIN,
411   ECOND_MATCH_IP,
412   ECOND_MATCH_LOCAL_PART,
413   ECOND_OR,
414   ECOND_PAM,
415   ECOND_PWCHECK,
416   ECOND_QUEUE_RUNNING,
417   ECOND_RADIUS,
418   ECOND_SASLAUTHD
419 };
420
421
422 /* Types of table entry */
423
424 enum vtypes {
425   vtype_int,            /* value is address of int */
426   vtype_filter_int,     /* ditto, but recognized only when filtering */
427   vtype_ino,            /* value is address of ino_t (not always an int) */
428   vtype_uid,            /* value is address of uid_t (not always an int) */
429   vtype_gid,            /* value is address of gid_t (not always an int) */
430   vtype_bool,           /* value is address of bool */
431   vtype_stringptr,      /* value is address of pointer to string */
432   vtype_msgbody,        /* as stringptr, but read when first required */
433   vtype_msgbody_end,    /* ditto, the end of the message */
434   vtype_msgheaders,     /* the message's headers, processed */
435   vtype_msgheaders_raw, /* the message's headers, unprocessed */
436   vtype_localpart,      /* extract local part from string */
437   vtype_domain,         /* extract domain from string */
438   vtype_string_func,    /* value is string returned by given function */
439   vtype_todbsdin,       /* value not used; generate BSD inbox tod */
440   vtype_tode,           /* value not used; generate tod in epoch format */
441   vtype_todel,          /* value not used; generate tod in epoch/usec format */
442   vtype_todf,           /* value not used; generate full tod */
443   vtype_todl,           /* value not used; generate log tod */
444   vtype_todlf,          /* value not used; generate log file datestamp tod */
445   vtype_todzone,        /* value not used; generate time zone only */
446   vtype_todzulu,        /* value not used; generate zulu tod */
447   vtype_reply,          /* value not used; get reply from headers */
448   vtype_pid,            /* value not used; result is pid */
449   vtype_host_lookup,    /* value not used; get host name */
450   vtype_load_avg,       /* value not used; result is int from os_getloadavg */
451   vtype_pspace,         /* partition space; value is T/F for spool/log */
452   vtype_pinodes,        /* partition inodes; value is T/F for spool/log */
453   vtype_cert            /* SSL certificate */
454 #ifndef DISABLE_DKIM
455   ,vtype_dkim           /* Lookup of value in DKIM signature */
456 #endif
457 };
458
459 /* Type for main variable table */
460
461 typedef struct {
462   const char *name;
463   enum vtypes type;
464   void       *value;
465 } var_entry;
466
467 /* Type for entries pointing to address/length pairs. Not currently
468 in use. */
469
470 typedef struct {
471   uschar **address;
472   int  *length;
473 } alblock;
474
475 static uschar * fn_recipients(void);
476 typedef uschar * stringptr_fn_t(void);
477 static uschar * fn_queue_size(void);
478
479 /* This table must be kept in alphabetical order. */
480
481 static var_entry var_table[] = {
482   /* WARNING: Do not invent variables whose names start acl_c or acl_m because
483      they will be confused with user-creatable ACL variables. */
484   { "acl_arg1",            vtype_stringptr,   &acl_arg[0] },
485   { "acl_arg2",            vtype_stringptr,   &acl_arg[1] },
486   { "acl_arg3",            vtype_stringptr,   &acl_arg[2] },
487   { "acl_arg4",            vtype_stringptr,   &acl_arg[3] },
488   { "acl_arg5",            vtype_stringptr,   &acl_arg[4] },
489   { "acl_arg6",            vtype_stringptr,   &acl_arg[5] },
490   { "acl_arg7",            vtype_stringptr,   &acl_arg[6] },
491   { "acl_arg8",            vtype_stringptr,   &acl_arg[7] },
492   { "acl_arg9",            vtype_stringptr,   &acl_arg[8] },
493   { "acl_narg",            vtype_int,         &acl_narg },
494   { "acl_verify_message",  vtype_stringptr,   &acl_verify_message },
495   { "address_data",        vtype_stringptr,   &deliver_address_data },
496   { "address_file",        vtype_stringptr,   &address_file },
497   { "address_pipe",        vtype_stringptr,   &address_pipe },
498 #ifdef EXPERIMENTAL_ARC
499   { "arc_domains",         vtype_string_func, (void *) &fn_arc_domains },
500   { "arc_oldest_pass",     vtype_int,         &arc_oldest_pass },
501   { "arc_state",           vtype_stringptr,   &arc_state },
502   { "arc_state_reason",    vtype_stringptr,   &arc_state_reason },
503 #endif
504   { "authenticated_fail_id",vtype_stringptr,  &authenticated_fail_id },
505   { "authenticated_id",    vtype_stringptr,   &authenticated_id },
506   { "authenticated_sender",vtype_stringptr,   &authenticated_sender },
507   { "authentication_failed",vtype_int,        &authentication_failed },
508 #ifdef WITH_CONTENT_SCAN
509   { "av_failed",           vtype_int,         &av_failed },
510 #endif
511 #ifdef EXPERIMENTAL_BRIGHTMAIL
512   { "bmi_alt_location",    vtype_stringptr,   &bmi_alt_location },
513   { "bmi_base64_tracker_verdict", vtype_stringptr, &bmi_base64_tracker_verdict },
514   { "bmi_base64_verdict",  vtype_stringptr,   &bmi_base64_verdict },
515   { "bmi_deliver",         vtype_int,         &bmi_deliver },
516 #endif
517   { "body_linecount",      vtype_int,         &body_linecount },
518   { "body_zerocount",      vtype_int,         &body_zerocount },
519   { "bounce_recipient",    vtype_stringptr,   &bounce_recipient },
520   { "bounce_return_size_limit", vtype_int,    &bounce_return_size_limit },
521   { "caller_gid",          vtype_gid,         &real_gid },
522   { "caller_uid",          vtype_uid,         &real_uid },
523   { "callout_address",     vtype_stringptr,   &callout_address },
524   { "compile_date",        vtype_stringptr,   &version_date },
525   { "compile_number",      vtype_stringptr,   &version_cnumber },
526   { "config_dir",          vtype_stringptr,   &config_main_directory },
527   { "config_file",         vtype_stringptr,   &config_main_filename },
528   { "csa_status",          vtype_stringptr,   &csa_status },
529 #ifdef EXPERIMENTAL_DCC
530   { "dcc_header",          vtype_stringptr,   &dcc_header },
531   { "dcc_result",          vtype_stringptr,   &dcc_result },
532 #endif
533 #ifndef DISABLE_DKIM
534   { "dkim_algo",           vtype_dkim,        (void *)DKIM_ALGO },
535   { "dkim_bodylength",     vtype_dkim,        (void *)DKIM_BODYLENGTH },
536   { "dkim_canon_body",     vtype_dkim,        (void *)DKIM_CANON_BODY },
537   { "dkim_canon_headers",  vtype_dkim,        (void *)DKIM_CANON_HEADERS },
538   { "dkim_copiedheaders",  vtype_dkim,        (void *)DKIM_COPIEDHEADERS },
539   { "dkim_created",        vtype_dkim,        (void *)DKIM_CREATED },
540   { "dkim_cur_signer",     vtype_stringptr,   &dkim_cur_signer },
541   { "dkim_domain",         vtype_stringptr,   &dkim_signing_domain },
542   { "dkim_expires",        vtype_dkim,        (void *)DKIM_EXPIRES },
543   { "dkim_headernames",    vtype_dkim,        (void *)DKIM_HEADERNAMES },
544   { "dkim_identity",       vtype_dkim,        (void *)DKIM_IDENTITY },
545   { "dkim_key_granularity",vtype_dkim,        (void *)DKIM_KEY_GRANULARITY },
546   { "dkim_key_length",     vtype_int,         &dkim_key_length },
547   { "dkim_key_nosubdomains",vtype_dkim,       (void *)DKIM_NOSUBDOMAINS },
548   { "dkim_key_notes",      vtype_dkim,        (void *)DKIM_KEY_NOTES },
549   { "dkim_key_srvtype",    vtype_dkim,        (void *)DKIM_KEY_SRVTYPE },
550   { "dkim_key_testing",    vtype_dkim,        (void *)DKIM_KEY_TESTING },
551   { "dkim_selector",       vtype_stringptr,   &dkim_signing_selector },
552   { "dkim_signers",        vtype_stringptr,   &dkim_signers },
553   { "dkim_verify_reason",  vtype_stringptr,   &dkim_verify_reason },
554   { "dkim_verify_status",  vtype_stringptr,   &dkim_verify_status },
555 #endif
556 #ifdef SUPPORT_DMARC
557   { "dmarc_domain_policy", vtype_stringptr,   &dmarc_domain_policy },
558   { "dmarc_status",        vtype_stringptr,   &dmarc_status },
559   { "dmarc_status_text",   vtype_stringptr,   &dmarc_status_text },
560   { "dmarc_used_domain",   vtype_stringptr,   &dmarc_used_domain },
561 #endif
562   { "dnslist_domain",      vtype_stringptr,   &dnslist_domain },
563   { "dnslist_matched",     vtype_stringptr,   &dnslist_matched },
564   { "dnslist_text",        vtype_stringptr,   &dnslist_text },
565   { "dnslist_value",       vtype_stringptr,   &dnslist_value },
566   { "domain",              vtype_stringptr,   &deliver_domain },
567   { "domain_data",         vtype_stringptr,   &deliver_domain_data },
568 #ifndef DISABLE_EVENT
569   { "event_data",          vtype_stringptr,   &event_data },
570
571   /*XXX want to use generic vars for as many of these as possible*/
572   { "event_defer_errno",   vtype_int,         &event_defer_errno },
573
574   { "event_name",          vtype_stringptr,   &event_name },
575 #endif
576   { "exim_gid",            vtype_gid,         &exim_gid },
577   { "exim_path",           vtype_stringptr,   &exim_path },
578   { "exim_uid",            vtype_uid,         &exim_uid },
579   { "exim_version",        vtype_stringptr,   &version_string },
580   { "headers_added",       vtype_string_func, (void *) &fn_hdrs_added },
581   { "home",                vtype_stringptr,   &deliver_home },
582   { "host",                vtype_stringptr,   &deliver_host },
583   { "host_address",        vtype_stringptr,   &deliver_host_address },
584   { "host_data",           vtype_stringptr,   &host_data },
585   { "host_lookup_deferred",vtype_int,         &host_lookup_deferred },
586   { "host_lookup_failed",  vtype_int,         &host_lookup_failed },
587   { "host_port",           vtype_int,         &deliver_host_port },
588   { "initial_cwd",         vtype_stringptr,   &initial_cwd },
589   { "inode",               vtype_ino,         &deliver_inode },
590   { "interface_address",   vtype_stringptr,   &interface_address },
591   { "interface_port",      vtype_int,         &interface_port },
592   { "item",                vtype_stringptr,   &iterate_item },
593 #ifdef LOOKUP_LDAP
594   { "ldap_dn",             vtype_stringptr,   &eldap_dn },
595 #endif
596   { "load_average",        vtype_load_avg,    NULL },
597   { "local_part",          vtype_stringptr,   &deliver_localpart },
598   { "local_part_data",     vtype_stringptr,   &deliver_localpart_data },
599   { "local_part_prefix",   vtype_stringptr,   &deliver_localpart_prefix },
600   { "local_part_prefix_v", vtype_stringptr,   &deliver_localpart_prefix_v },
601   { "local_part_suffix",   vtype_stringptr,   &deliver_localpart_suffix },
602   { "local_part_suffix_v", vtype_stringptr,   &deliver_localpart_suffix_v },
603 #ifdef HAVE_LOCAL_SCAN
604   { "local_scan_data",     vtype_stringptr,   &local_scan_data },
605 #endif
606   { "local_user_gid",      vtype_gid,         &local_user_gid },
607   { "local_user_uid",      vtype_uid,         &local_user_uid },
608   { "localhost_number",    vtype_int,         &host_number },
609   { "log_inodes",          vtype_pinodes,     (void *)FALSE },
610   { "log_space",           vtype_pspace,      (void *)FALSE },
611   { "lookup_dnssec_authenticated",vtype_stringptr,&lookup_dnssec_authenticated},
612   { "mailstore_basename",  vtype_stringptr,   &mailstore_basename },
613 #ifdef WITH_CONTENT_SCAN
614   { "malware_name",        vtype_stringptr,   &malware_name },
615 #endif
616   { "max_received_linelength", vtype_int,     &max_received_linelength },
617   { "message_age",         vtype_int,         &message_age },
618   { "message_body",        vtype_msgbody,     &message_body },
619   { "message_body_end",    vtype_msgbody_end, &message_body_end },
620   { "message_body_size",   vtype_int,         &message_body_size },
621   { "message_exim_id",     vtype_stringptr,   &message_id },
622   { "message_headers",     vtype_msgheaders,  NULL },
623   { "message_headers_raw", vtype_msgheaders_raw, NULL },
624   { "message_id",          vtype_stringptr,   &message_id },
625   { "message_linecount",   vtype_int,         &message_linecount },
626   { "message_size",        vtype_int,         &message_size },
627 #ifdef SUPPORT_I18N
628   { "message_smtputf8",    vtype_bool,        &message_smtputf8 },
629 #endif
630 #ifdef WITH_CONTENT_SCAN
631   { "mime_anomaly_level",  vtype_int,         &mime_anomaly_level },
632   { "mime_anomaly_text",   vtype_stringptr,   &mime_anomaly_text },
633   { "mime_boundary",       vtype_stringptr,   &mime_boundary },
634   { "mime_charset",        vtype_stringptr,   &mime_charset },
635   { "mime_content_description", vtype_stringptr, &mime_content_description },
636   { "mime_content_disposition", vtype_stringptr, &mime_content_disposition },
637   { "mime_content_id",     vtype_stringptr,   &mime_content_id },
638   { "mime_content_size",   vtype_int,         &mime_content_size },
639   { "mime_content_transfer_encoding",vtype_stringptr, &mime_content_transfer_encoding },
640   { "mime_content_type",   vtype_stringptr,   &mime_content_type },
641   { "mime_decoded_filename", vtype_stringptr, &mime_decoded_filename },
642   { "mime_filename",       vtype_stringptr,   &mime_filename },
643   { "mime_is_coverletter", vtype_int,         &mime_is_coverletter },
644   { "mime_is_multipart",   vtype_int,         &mime_is_multipart },
645   { "mime_is_rfc822",      vtype_int,         &mime_is_rfc822 },
646   { "mime_part_count",     vtype_int,         &mime_part_count },
647 #endif
648   { "n0",                  vtype_filter_int,  &filter_n[0] },
649   { "n1",                  vtype_filter_int,  &filter_n[1] },
650   { "n2",                  vtype_filter_int,  &filter_n[2] },
651   { "n3",                  vtype_filter_int,  &filter_n[3] },
652   { "n4",                  vtype_filter_int,  &filter_n[4] },
653   { "n5",                  vtype_filter_int,  &filter_n[5] },
654   { "n6",                  vtype_filter_int,  &filter_n[6] },
655   { "n7",                  vtype_filter_int,  &filter_n[7] },
656   { "n8",                  vtype_filter_int,  &filter_n[8] },
657   { "n9",                  vtype_filter_int,  &filter_n[9] },
658   { "original_domain",     vtype_stringptr,   &deliver_domain_orig },
659   { "original_local_part", vtype_stringptr,   &deliver_localpart_orig },
660   { "originator_gid",      vtype_gid,         &originator_gid },
661   { "originator_uid",      vtype_uid,         &originator_uid },
662   { "parent_domain",       vtype_stringptr,   &deliver_domain_parent },
663   { "parent_local_part",   vtype_stringptr,   &deliver_localpart_parent },
664   { "pid",                 vtype_pid,         NULL },
665 #ifndef DISABLE_PRDR
666   { "prdr_requested",      vtype_bool,        &prdr_requested },
667 #endif
668   { "primary_hostname",    vtype_stringptr,   &primary_hostname },
669 #if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
670   { "proxy_external_address",vtype_stringptr, &proxy_external_address },
671   { "proxy_external_port", vtype_int,         &proxy_external_port },
672   { "proxy_local_address", vtype_stringptr,   &proxy_local_address },
673   { "proxy_local_port",    vtype_int,         &proxy_local_port },
674   { "proxy_session",       vtype_bool,        &proxy_session },
675 #endif
676   { "prvscheck_address",   vtype_stringptr,   &prvscheck_address },
677   { "prvscheck_keynum",    vtype_stringptr,   &prvscheck_keynum },
678   { "prvscheck_result",    vtype_stringptr,   &prvscheck_result },
679   { "qualify_domain",      vtype_stringptr,   &qualify_domain_sender },
680   { "qualify_recipient",   vtype_stringptr,   &qualify_domain_recipient },
681   { "queue_name",          vtype_stringptr,   &queue_name },
682   { "queue_size",          vtype_string_func, &fn_queue_size },
683   { "rcpt_count",          vtype_int,         &rcpt_count },
684   { "rcpt_defer_count",    vtype_int,         &rcpt_defer_count },
685   { "rcpt_fail_count",     vtype_int,         &rcpt_fail_count },
686   { "received_count",      vtype_int,         &received_count },
687   { "received_for",        vtype_stringptr,   &received_for },
688   { "received_ip_address", vtype_stringptr,   &interface_address },
689   { "received_port",       vtype_int,         &interface_port },
690   { "received_protocol",   vtype_stringptr,   &received_protocol },
691   { "received_time",       vtype_int,         &received_time.tv_sec },
692   { "recipient_data",      vtype_stringptr,   &recipient_data },
693   { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
694   { "recipients",          vtype_string_func, (void *) &fn_recipients },
695   { "recipients_count",    vtype_int,         &recipients_count },
696   { "regex_cachesize",     vtype_int,         &regex_cachesize },/* undocumented; devel observability */
697 #ifdef WITH_CONTENT_SCAN
698   { "regex_match_string",  vtype_stringptr,   &regex_match_string },
699 #endif
700   { "reply_address",       vtype_reply,       NULL },
701   { "return_path",         vtype_stringptr,   &return_path },
702   { "return_size_limit",   vtype_int,         &bounce_return_size_limit },
703   { "router_name",         vtype_stringptr,   &router_name },
704   { "runrc",               vtype_int,         &runrc },
705   { "self_hostname",       vtype_stringptr,   &self_hostname },
706   { "sender_address",      vtype_stringptr,   &sender_address },
707   { "sender_address_data", vtype_stringptr,   &sender_address_data },
708   { "sender_address_domain", vtype_domain,    &sender_address },
709   { "sender_address_local_part", vtype_localpart, &sender_address },
710   { "sender_data",         vtype_stringptr,   &sender_data },
711   { "sender_fullhost",     vtype_stringptr,   &sender_fullhost },
712   { "sender_helo_dnssec",  vtype_bool,        &sender_helo_dnssec },
713   { "sender_helo_name",    vtype_stringptr,   &sender_helo_name },
714   { "sender_host_address", vtype_stringptr,   &sender_host_address },
715   { "sender_host_authenticated",vtype_stringptr, &sender_host_authenticated },
716   { "sender_host_dnssec",  vtype_bool,        &sender_host_dnssec },
717   { "sender_host_name",    vtype_host_lookup, NULL },
718   { "sender_host_port",    vtype_int,         &sender_host_port },
719   { "sender_ident",        vtype_stringptr,   &sender_ident },
720   { "sender_rate",         vtype_stringptr,   &sender_rate },
721   { "sender_rate_limit",   vtype_stringptr,   &sender_rate_limit },
722   { "sender_rate_period",  vtype_stringptr,   &sender_rate_period },
723   { "sender_rcvhost",      vtype_stringptr,   &sender_rcvhost },
724   { "sender_verify_failure",vtype_stringptr,  &sender_verify_failure },
725   { "sending_ip_address",  vtype_stringptr,   &sending_ip_address },
726   { "sending_port",        vtype_int,         &sending_port },
727   { "smtp_active_hostname", vtype_stringptr,  &smtp_active_hostname },
728   { "smtp_command",        vtype_stringptr,   &smtp_cmd_buffer },
729   { "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument },
730   { "smtp_command_history", vtype_string_func, (void *) &smtp_cmd_hist },
731   { "smtp_count_at_connection_start", vtype_int, &smtp_accept_count },
732   { "smtp_notquit_reason", vtype_stringptr,   &smtp_notquit_reason },
733   { "sn0",                 vtype_filter_int,  &filter_sn[0] },
734   { "sn1",                 vtype_filter_int,  &filter_sn[1] },
735   { "sn2",                 vtype_filter_int,  &filter_sn[2] },
736   { "sn3",                 vtype_filter_int,  &filter_sn[3] },
737   { "sn4",                 vtype_filter_int,  &filter_sn[4] },
738   { "sn5",                 vtype_filter_int,  &filter_sn[5] },
739   { "sn6",                 vtype_filter_int,  &filter_sn[6] },
740   { "sn7",                 vtype_filter_int,  &filter_sn[7] },
741   { "sn8",                 vtype_filter_int,  &filter_sn[8] },
742   { "sn9",                 vtype_filter_int,  &filter_sn[9] },
743 #ifdef WITH_CONTENT_SCAN
744   { "spam_action",         vtype_stringptr,   &spam_action },
745   { "spam_bar",            vtype_stringptr,   &spam_bar },
746   { "spam_report",         vtype_stringptr,   &spam_report },
747   { "spam_score",          vtype_stringptr,   &spam_score },
748   { "spam_score_int",      vtype_stringptr,   &spam_score_int },
749 #endif
750 #ifdef SUPPORT_SPF
751   { "spf_guess",           vtype_stringptr,   &spf_guess },
752   { "spf_header_comment",  vtype_stringptr,   &spf_header_comment },
753   { "spf_received",        vtype_stringptr,   &spf_received },
754   { "spf_result",          vtype_stringptr,   &spf_result },
755   { "spf_result_guessed",  vtype_bool,        &spf_result_guessed },
756   { "spf_smtp_comment",    vtype_stringptr,   &spf_smtp_comment },
757 #endif
758   { "spool_directory",     vtype_stringptr,   &spool_directory },
759   { "spool_inodes",        vtype_pinodes,     (void *)TRUE },
760   { "spool_space",         vtype_pspace,      (void *)TRUE },
761 #ifdef SUPPORT_SRS
762   { "srs_recipient",       vtype_stringptr,   &srs_recipient },
763 #endif
764   { "thisaddress",         vtype_stringptr,   &filter_thisaddress },
765
766   /* The non-(in,out) variables are now deprecated */
767   { "tls_bits",            vtype_int,         &tls_in.bits },
768   { "tls_certificate_verified", vtype_int,    &tls_in.certificate_verified },
769   { "tls_cipher",          vtype_stringptr,   &tls_in.cipher },
770
771   { "tls_in_bits",         vtype_int,         &tls_in.bits },
772   { "tls_in_certificate_verified", vtype_int, &tls_in.certificate_verified },
773   { "tls_in_cipher",       vtype_stringptr,   &tls_in.cipher },
774   { "tls_in_cipher_std",   vtype_stringptr,   &tls_in.cipher_stdname },
775   { "tls_in_ocsp",         vtype_int,         &tls_in.ocsp },
776   { "tls_in_ourcert",      vtype_cert,        &tls_in.ourcert },
777   { "tls_in_peercert",     vtype_cert,        &tls_in.peercert },
778   { "tls_in_peerdn",       vtype_stringptr,   &tls_in.peerdn },
779 #ifndef DISABLE_TLS_RESUME
780   { "tls_in_resumption",   vtype_int,         &tls_in.resumption },
781 #endif
782 #ifndef DISABLE_TLS
783   { "tls_in_sni",          vtype_stringptr,   &tls_in.sni },
784 #endif
785   { "tls_in_ver",          vtype_stringptr,   &tls_in.ver },
786   { "tls_out_bits",        vtype_int,         &tls_out.bits },
787   { "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified },
788   { "tls_out_cipher",      vtype_stringptr,   &tls_out.cipher },
789   { "tls_out_cipher_std",  vtype_stringptr,   &tls_out.cipher_stdname },
790 #ifdef SUPPORT_DANE
791   { "tls_out_dane",        vtype_bool,        &tls_out.dane_verified },
792 #endif
793   { "tls_out_ocsp",        vtype_int,         &tls_out.ocsp },
794   { "tls_out_ourcert",     vtype_cert,        &tls_out.ourcert },
795   { "tls_out_peercert",    vtype_cert,        &tls_out.peercert },
796   { "tls_out_peerdn",      vtype_stringptr,   &tls_out.peerdn },
797 #ifndef DISABLE_TLS_RESUME
798   { "tls_out_resumption",  vtype_int,         &tls_out.resumption },
799 #endif
800 #ifndef DISABLE_TLS
801   { "tls_out_sni",         vtype_stringptr,   &tls_out.sni },
802 #endif
803 #ifdef SUPPORT_DANE
804   { "tls_out_tlsa_usage",  vtype_int,         &tls_out.tlsa_usage },
805 #endif
806   { "tls_out_ver",         vtype_stringptr,   &tls_out.ver },
807
808   { "tls_peerdn",          vtype_stringptr,   &tls_in.peerdn }, /* mind the alphabetical order! */
809 #ifndef DISABLE_TLS
810   { "tls_sni",             vtype_stringptr,   &tls_in.sni },    /* mind the alphabetical order! */
811 #endif
812
813   { "tod_bsdinbox",        vtype_todbsdin,    NULL },
814   { "tod_epoch",           vtype_tode,        NULL },
815   { "tod_epoch_l",         vtype_todel,       NULL },
816   { "tod_full",            vtype_todf,        NULL },
817   { "tod_log",             vtype_todl,        NULL },
818   { "tod_logfile",         vtype_todlf,       NULL },
819   { "tod_zone",            vtype_todzone,     NULL },
820   { "tod_zulu",            vtype_todzulu,     NULL },
821   { "transport_name",      vtype_stringptr,   &transport_name },
822   { "value",               vtype_stringptr,   &lookup_value },
823   { "verify_mode",         vtype_stringptr,   &verify_mode },
824   { "version_number",      vtype_stringptr,   &version_string },
825   { "warn_message_delay",  vtype_stringptr,   &warnmsg_delay },
826   { "warn_message_recipient",vtype_stringptr, &warnmsg_recipients },
827   { "warn_message_recipients",vtype_stringptr,&warnmsg_recipients },
828   { "warnmsg_delay",       vtype_stringptr,   &warnmsg_delay },
829   { "warnmsg_recipient",   vtype_stringptr,   &warnmsg_recipients },
830   { "warnmsg_recipients",  vtype_stringptr,   &warnmsg_recipients }
831 };
832
833 static int var_table_size = nelem(var_table);
834 static uschar var_buffer[256];
835 static BOOL malformed_header;
836
837 /* For textual hashes */
838
839 static const char *hashcodes = "abcdefghijklmnopqrtsuvwxyz"
840                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
841                                "0123456789";
842
843 enum { HMAC_MD5, HMAC_SHA1 };
844
845 /* For numeric hashes */
846
847 static unsigned int prime[] = {
848   2,   3,   5,   7,  11,  13,  17,  19,  23,  29,
849  31,  37,  41,  43,  47,  53,  59,  61,  67,  71,
850  73,  79,  83,  89,  97, 101, 103, 107, 109, 113};
851
852 /* For printing modes in symbolic form */
853
854 static uschar *mtable_normal[] =
855   { US"---", US"--x", US"-w-", US"-wx", US"r--", US"r-x", US"rw-", US"rwx" };
856
857 static uschar *mtable_setid[] =
858   { US"--S", US"--s", US"-wS", US"-ws", US"r-S", US"r-s", US"rwS", US"rws" };
859
860 static uschar *mtable_sticky[] =
861   { US"--T", US"--t", US"-wT", US"-wt", US"r-T", US"r-t", US"rwT", US"rwt" };
862
863 /* flags for find_header() */
864 #define FH_EXISTS_ONLY  BIT(0)
865 #define FH_WANT_RAW     BIT(1)
866 #define FH_WANT_LIST    BIT(2)
867
868
869 /*************************************************
870 *           Tables for UTF-8 support             *
871 *************************************************/
872
873 /* Table of the number of extra characters, indexed by the first character
874 masked with 0x3f. The highest number for a valid UTF-8 character is in fact
875 0x3d. */
876
877 static uschar utf8_table1[] = {
878   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
879   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
880   2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
881   3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
882
883 /* These are the masks for the data bits in the first byte of a character,
884 indexed by the number of additional bytes. */
885
886 static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
887
888 /* Get the next UTF-8 character, advancing the pointer. */
889
890 #define GETUTF8INC(c, ptr) \
891   c = *ptr++; \
892   if ((c & 0xc0) == 0xc0) \
893     { \
894     int a = utf8_table1[c & 0x3f];  /* Number of additional bytes */ \
895     int s = 6*a; \
896     c = (c & utf8_table2[a]) << s; \
897     while (a-- > 0) \
898       { \
899       s -= 6; \
900       c |= (*ptr++ & 0x3f) << s; \
901       } \
902     }
903
904
905
906 static uschar * base32_chars = US"abcdefghijklmnopqrstuvwxyz234567";
907
908 /*************************************************
909 *           Binary chop search on a table        *
910 *************************************************/
911
912 /* This is used for matching expansion items and operators.
913
914 Arguments:
915   name        the name that is being sought
916   table       the table to search
917   table_size  the number of items in the table
918
919 Returns:      the offset in the table, or -1
920 */
921
922 static int
923 chop_match(uschar *name, uschar **table, int table_size)
924 {
925 uschar **bot = table;
926 uschar **top = table + table_size;
927
928 while (top > bot)
929   {
930   uschar **mid = bot + (top - bot)/2;
931   int c = Ustrcmp(name, *mid);
932   if (c == 0) return mid - table;
933   if (c > 0) bot = mid + 1; else top = mid;
934   }
935
936 return -1;
937 }
938
939
940
941 /*************************************************
942 *          Check a condition string              *
943 *************************************************/
944
945 /* This function is called to expand a string, and test the result for a "true"
946 or "false" value. Failure of the expansion yields FALSE; logged unless it was a
947 forced fail or lookup defer.
948
949 We used to release all store used, but this is not not safe due
950 to ${dlfunc } and ${acl }.  In any case expand_string_internal()
951 is reasonably careful to release what it can.
952
953 The actual false-value tests should be replicated for ECOND_BOOL_LAX.
954
955 Arguments:
956   condition     the condition string
957   m1            text to be incorporated in panic error
958   m2            ditto
959
960 Returns:        TRUE if condition is met, FALSE if not
961 */
962
963 BOOL
964 expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
965 {
966 uschar * ss = expand_string(condition);
967 if (!ss)
968   {
969   if (!f.expand_string_forcedfail && !f.search_find_defer)
970     log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand condition \"%s\" "
971       "for %s %s: %s", condition, m1, m2, expand_string_message);
972   return FALSE;
973   }
974 return *ss && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
975   strcmpic(ss, US"false") != 0;
976 }
977
978
979
980
981 /*************************************************
982 *        Pseudo-random number generation         *
983 *************************************************/
984
985 /* Pseudo-random number generation.  The result is not "expected" to be
986 cryptographically strong but not so weak that someone will shoot themselves
987 in the foot using it as a nonce in some email header scheme or whatever
988 weirdness they'll twist this into.  The result should ideally handle fork().
989
990 However, if we're stuck unable to provide this, then we'll fall back to
991 appallingly bad randomness.
992
993 If DISABLE_TLS is not defined then this will not be used except as an emergency
994 fallback.
995
996 Arguments:
997   max       range maximum
998 Returns     a random number in range [0, max-1]
999 */
1000
1001 #ifndef DISABLE_TLS
1002 # define vaguely_random_number vaguely_random_number_fallback
1003 #endif
1004 int
1005 vaguely_random_number(int max)
1006 {
1007 #ifndef DISABLE_TLS
1008 # undef vaguely_random_number
1009 #endif
1010 static pid_t pid = 0;
1011 pid_t p2;
1012
1013 if ((p2 = getpid()) != pid)
1014   {
1015   if (pid != 0)
1016     {
1017
1018 #ifdef HAVE_ARC4RANDOM
1019     /* cryptographically strong randomness, common on *BSD platforms, not
1020     so much elsewhere.  Alas. */
1021 # ifndef NOT_HAVE_ARC4RANDOM_STIR
1022     arc4random_stir();
1023 # endif
1024 #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
1025 # ifdef HAVE_SRANDOMDEV
1026     /* uses random(4) for seeding */
1027     srandomdev();
1028 # else
1029     {
1030     struct timeval tv;
1031     gettimeofday(&tv, NULL);
1032     srandom(tv.tv_sec | tv.tv_usec | getpid());
1033     }
1034 # endif
1035 #else
1036     /* Poor randomness and no seeding here */
1037 #endif
1038
1039     }
1040   pid = p2;
1041   }
1042
1043 #ifdef HAVE_ARC4RANDOM
1044 return arc4random() % max;
1045 #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
1046 return random() % max;
1047 #else
1048 /* This one returns a 16-bit number, definitely not crypto-strong */
1049 return random_number(max);
1050 #endif
1051 }
1052
1053
1054
1055
1056 /*************************************************
1057 *             Pick out a name from a string      *
1058 *************************************************/
1059
1060 /* If the name is too long, it is silently truncated.
1061
1062 Arguments:
1063   name      points to a buffer into which to put the name
1064   max       is the length of the buffer
1065   s         points to the first alphabetic character of the name
1066   extras    chars other than alphanumerics to permit
1067
1068 Returns:    pointer to the first character after the name
1069
1070 Note: The test for *s != 0 in the while loop is necessary because
1071 Ustrchr() yields non-NULL if the character is zero (which is not something
1072 I expected). */
1073
1074 static const uschar *
1075 read_name(uschar *name, int max, const uschar *s, uschar *extras)
1076 {
1077 int ptr = 0;
1078 while (*s && (isalnum(*s) || Ustrchr(extras, *s) != NULL))
1079   {
1080   if (ptr < max-1) name[ptr++] = *s;
1081   s++;
1082   }
1083 name[ptr] = 0;
1084 return s;
1085 }
1086
1087
1088
1089 /*************************************************
1090 *     Pick out the rest of a header name         *
1091 *************************************************/
1092
1093 /* A variable name starting $header_ (or just $h_ for those who like
1094 abbreviations) might not be the complete header name because headers can
1095 contain any printing characters in their names, except ':'. This function is
1096 called to read the rest of the name, chop h[eader]_ off the front, and put ':'
1097 on the end, if the name was terminated by white space.
1098
1099 Arguments:
1100   name      points to a buffer in which the name read so far exists
1101   max       is the length of the buffer
1102   s         points to the first character after the name so far, i.e. the
1103             first non-alphameric character after $header_xxxxx
1104
1105 Returns:    a pointer to the first character after the header name
1106 */
1107
1108 static const uschar *
1109 read_header_name(uschar *name, int max, const uschar *s)
1110 {
1111 int prelen = Ustrchr(name, '_') - name + 1;
1112 int ptr = Ustrlen(name) - prelen;
1113 if (ptr > 0) memmove(name, name+prelen, ptr);
1114 while (mac_isgraph(*s) && *s != ':')
1115   {
1116   if (ptr < max-1) name[ptr++] = *s;
1117   s++;
1118   }
1119 if (*s == ':') s++;
1120 name[ptr++] = ':';
1121 name[ptr] = 0;
1122 return s;
1123 }
1124
1125
1126
1127 /*************************************************
1128 *           Pick out a number from a string      *
1129 *************************************************/
1130
1131 /* Arguments:
1132   n     points to an integer into which to put the number
1133   s     points to the first digit of the number
1134
1135 Returns:  a pointer to the character after the last digit
1136 */
1137 /*XXX consider expanding to int_eximarith_t.  But the test for
1138 "overbig numbers" in 0002 still needs to overflow it. */
1139
1140 static uschar *
1141 read_number(int *n, uschar *s)
1142 {
1143 *n = 0;
1144 while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
1145 return s;
1146 }
1147
1148 static const uschar *
1149 read_cnumber(int *n, const uschar *s)
1150 {
1151 *n = 0;
1152 while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
1153 return s;
1154 }
1155
1156
1157
1158 /*************************************************
1159 *        Extract keyed subfield from a string    *
1160 *************************************************/
1161
1162 /* The yield is in dynamic store; NULL means that the key was not found.
1163
1164 Arguments:
1165   key       points to the name of the key
1166   s         points to the string from which to extract the subfield
1167
1168 Returns:    NULL if the subfield was not found, or
1169             a pointer to the subfield's data
1170 */
1171
1172 uschar *
1173 expand_getkeyed(const uschar * key, const uschar * s)
1174 {
1175 int length = Ustrlen(key);
1176 Uskip_whitespace(&s);
1177
1178 /* Loop to search for the key */
1179
1180 while (*s)
1181   {
1182   int dkeylength;
1183   uschar * data;
1184   const uschar * dkey = s;
1185
1186   while (*s && *s != '=' && !isspace(*s)) s++;
1187   dkeylength = s - dkey;
1188   if (Uskip_whitespace(&s) == '=') while (isspace(*++s));
1189
1190   data = string_dequote(&s);
1191   if (length == dkeylength && strncmpic(key, dkey, length) == 0)
1192     return data;
1193
1194   Uskip_whitespace(&s);
1195   }
1196
1197 return NULL;
1198 }
1199
1200
1201
1202 static var_entry *
1203 find_var_ent(uschar * name)
1204 {
1205 int first = 0;
1206 int last = var_table_size;
1207
1208 while (last > first)
1209   {
1210   int middle = (first + last)/2;
1211   int c = Ustrcmp(name, var_table[middle].name);
1212
1213   if (c > 0) { first = middle + 1; continue; }
1214   if (c < 0) { last = middle; continue; }
1215   return &var_table[middle];
1216   }
1217 return NULL;
1218 }
1219
1220 /*************************************************
1221 *   Extract numbered subfield from string        *
1222 *************************************************/
1223
1224 /* Extracts a numbered field from a string that is divided by tokens - for
1225 example a line from /etc/passwd is divided by colon characters.  First field is
1226 numbered one.  Negative arguments count from the right. Zero returns the whole
1227 string. Returns NULL if there are insufficient tokens in the string
1228
1229 ***WARNING***
1230 Modifies final argument - this is a dynamically generated string, so that's OK.
1231
1232 Arguments:
1233   field       number of field to be extracted,
1234                 first field = 1, whole string = 0, last field = -1
1235   separators  characters that are used to break string into tokens
1236   s           points to the string from which to extract the subfield
1237
1238 Returns:      NULL if the field was not found,
1239               a pointer to the field's data inside s (modified to add 0)
1240 */
1241
1242 static uschar *
1243 expand_gettokened (int field, uschar *separators, uschar *s)
1244 {
1245 int sep = 1;
1246 int count;
1247 uschar *ss = s;
1248 uschar *fieldtext = NULL;
1249
1250 if (field == 0) return s;
1251
1252 /* Break the line up into fields in place; for field > 0 we stop when we have
1253 done the number of fields we want. For field < 0 we continue till the end of
1254 the string, counting the number of fields. */
1255
1256 count = (field > 0)? field : INT_MAX;
1257
1258 while (count-- > 0)
1259   {
1260   size_t len;
1261
1262   /* Previous field was the last one in the string. For a positive field
1263   number, this means there are not enough fields. For a negative field number,
1264   check that there are enough, and scan back to find the one that is wanted. */
1265
1266   if (sep == 0)
1267     {
1268     if (field > 0 || (-field) > (INT_MAX - count - 1)) return NULL;
1269     if ((-field) == (INT_MAX - count - 1)) return s;
1270     while (field++ < 0)
1271       {
1272       ss--;
1273       while (ss[-1] != 0) ss--;
1274       }
1275     fieldtext = ss;
1276     break;
1277     }
1278
1279   /* Previous field was not last in the string; save its start and put a
1280   zero at its end. */
1281
1282   fieldtext = ss;
1283   len = Ustrcspn(ss, separators);
1284   sep = ss[len];
1285   ss[len] = 0;
1286   ss += len + 1;
1287   }
1288
1289 return fieldtext;
1290 }
1291
1292
1293 static uschar *
1294 expand_getlistele(int field, const uschar * list)
1295 {
1296 const uschar * tlist = list;
1297 int sep = 0;
1298 /* Tainted mem for the throwaway element copies */
1299 uschar * dummy = store_get(2, GET_TAINTED);
1300
1301 if (field < 0)
1302   {
1303   for (field++; string_nextinlist(&tlist, &sep, dummy, 1); ) field++;
1304   sep = 0;
1305   }
1306 if (field == 0) return NULL;
1307 while (--field > 0 && (string_nextinlist(&list, &sep, dummy, 1))) ;
1308 return string_nextinlist(&list, &sep, NULL, 0);
1309 }
1310
1311
1312 /* Certificate fields, by name.  Worry about by-OID later */
1313 /* Names are chosen to not have common prefixes */
1314
1315 #ifndef DISABLE_TLS
1316 typedef struct
1317 {
1318 uschar * name;
1319 int      namelen;
1320 uschar * (*getfn)(void * cert, uschar * mod);
1321 } certfield;
1322 static certfield certfields[] =
1323 {                       /* linear search; no special order */
1324   { US"version",         7,  &tls_cert_version },
1325   { US"serial_number",   13, &tls_cert_serial_number },
1326   { US"subject",         7,  &tls_cert_subject },
1327   { US"notbefore",       9,  &tls_cert_not_before },
1328   { US"notafter",        8,  &tls_cert_not_after },
1329   { US"issuer",          6,  &tls_cert_issuer },
1330   { US"signature",       9,  &tls_cert_signature },
1331   { US"sig_algorithm",   13, &tls_cert_signature_algorithm },
1332   { US"subj_altname",    12, &tls_cert_subject_altname },
1333   { US"ocsp_uri",        8,  &tls_cert_ocsp_uri },
1334   { US"crl_uri",         7,  &tls_cert_crl_uri },
1335 };
1336
1337 static uschar *
1338 expand_getcertele(uschar * field, uschar * certvar)
1339 {
1340 var_entry * vp;
1341
1342 if (!(vp = find_var_ent(certvar)))
1343   {
1344   expand_string_message =
1345     string_sprintf("no variable named \"%s\"", certvar);
1346   return NULL;          /* Unknown variable name */
1347   }
1348 /* NB this stops us passing certs around in variable.  Might
1349 want to do that in future */
1350 if (vp->type != vtype_cert)
1351   {
1352   expand_string_message =
1353     string_sprintf("\"%s\" is not a certificate", certvar);
1354   return NULL;          /* Unknown variable name */
1355   }
1356 if (!*(void **)vp->value)
1357   return NULL;
1358
1359 if (*field >= '0' && *field <= '9')
1360   return tls_cert_ext_by_oid(*(void **)vp->value, field, 0);
1361
1362 for (certfield * cp = certfields;
1363      cp < certfields + nelem(certfields);
1364      cp++)
1365   if (Ustrncmp(cp->name, field, cp->namelen) == 0)
1366     {
1367     uschar * modifier = *(field += cp->namelen) == ','
1368       ? ++field : NULL;
1369     return (*cp->getfn)( *(void **)vp->value, modifier );
1370     }
1371
1372 expand_string_message =
1373   string_sprintf("bad field selector \"%s\" for certextract", field);
1374 return NULL;
1375 }
1376 #endif  /*DISABLE_TLS*/
1377
1378 /*************************************************
1379 *        Extract a substring from a string       *
1380 *************************************************/
1381
1382 /* Perform the ${substr or ${length expansion operations.
1383
1384 Arguments:
1385   subject     the input string
1386   value1      the offset from the start of the input string to the start of
1387                 the output string; if negative, count from the right.
1388   value2      the length of the output string, or negative (-1) for unset
1389                 if value1 is positive, unset means "all after"
1390                 if value1 is negative, unset means "all before"
1391   len         set to the length of the returned string
1392
1393 Returns:      pointer to the output string, or NULL if there is an error
1394 */
1395
1396 static uschar *
1397 extract_substr(uschar *subject, int value1, int value2, int *len)
1398 {
1399 int sublen = Ustrlen(subject);
1400
1401 if (value1 < 0)    /* count from right */
1402   {
1403   value1 += sublen;
1404
1405   /* If the position is before the start, skip to the start, and adjust the
1406   length. If the length ends up negative, the substring is null because nothing
1407   can precede. This falls out naturally when the length is unset, meaning "all
1408   to the left". */
1409
1410   if (value1 < 0)
1411     {
1412     value2 += value1;
1413     if (value2 < 0) value2 = 0;
1414     value1 = 0;
1415     }
1416
1417   /* Otherwise an unset length => characters before value1 */
1418
1419   else if (value2 < 0)
1420     {
1421     value2 = value1;
1422     value1 = 0;
1423     }
1424   }
1425
1426 /* For a non-negative offset, if the starting position is past the end of the
1427 string, the result will be the null string. Otherwise, an unset length means
1428 "rest"; just set it to the maximum - it will be cut down below if necessary. */
1429
1430 else
1431   {
1432   if (value1 > sublen)
1433     {
1434     value1 = sublen;
1435     value2 = 0;
1436     }
1437   else if (value2 < 0) value2 = sublen;
1438   }
1439
1440 /* Cut the length down to the maximum possible for the offset value, and get
1441 the required characters. */
1442
1443 if (value1 + value2 > sublen) value2 = sublen - value1;
1444 *len = value2;
1445 return subject + value1;
1446 }
1447
1448
1449
1450
1451 /*************************************************
1452 *            Old-style hash of a string          *
1453 *************************************************/
1454
1455 /* Perform the ${hash expansion operation.
1456
1457 Arguments:
1458   subject     the input string (an expanded substring)
1459   value1      the length of the output string; if greater or equal to the
1460                 length of the input string, the input string is returned
1461   value2      the number of hash characters to use, or 26 if negative
1462   len         set to the length of the returned string
1463
1464 Returns:      pointer to the output string, or NULL if there is an error
1465 */
1466
1467 static uschar *
1468 compute_hash(uschar *subject, int value1, int value2, int *len)
1469 {
1470 int sublen = Ustrlen(subject);
1471
1472 if (value2 < 0) value2 = 26;
1473 else if (value2 > Ustrlen(hashcodes))
1474   {
1475   expand_string_message =
1476     string_sprintf("hash count \"%d\" too big", value2);
1477   return NULL;
1478   }
1479
1480 /* Calculate the hash text. We know it is shorter than the original string, so
1481 can safely place it in subject[] (we know that subject is always itself an
1482 expanded substring). */
1483
1484 if (value1 < sublen)
1485   {
1486   int c;
1487   int i = 0;
1488   int j = value1;
1489   while ((c = (subject[j])) != 0)
1490     {
1491     int shift = (c + j++) & 7;
1492     subject[i] ^= (c << shift) | (c >> (8-shift));
1493     if (++i >= value1) i = 0;
1494     }
1495   for (i = 0; i < value1; i++)
1496     subject[i] = hashcodes[(subject[i]) % value2];
1497   }
1498 else value1 = sublen;
1499
1500 *len = value1;
1501 return subject;
1502 }
1503
1504
1505
1506
1507 /*************************************************
1508 *             Numeric hash of a string           *
1509 *************************************************/
1510
1511 /* Perform the ${nhash expansion operation. The first characters of the
1512 string are treated as most important, and get the highest prime numbers.
1513
1514 Arguments:
1515   subject     the input string
1516   value1      the maximum value of the first part of the result
1517   value2      the maximum value of the second part of the result,
1518                 or negative to produce only a one-part result
1519   len         set to the length of the returned string
1520
1521 Returns:  pointer to the output string, or NULL if there is an error.
1522 */
1523
1524 static uschar *
1525 compute_nhash (uschar *subject, int value1, int value2, int *len)
1526 {
1527 uschar *s = subject;
1528 int i = 0;
1529 unsigned long int total = 0; /* no overflow */
1530
1531 while (*s != 0)
1532   {
1533   if (i == 0) i = nelem(prime) - 1;
1534   total += prime[i--] * (unsigned int)(*s++);
1535   }
1536
1537 /* If value2 is unset, just compute one number */
1538
1539 if (value2 < 0)
1540   s = string_sprintf("%lu", total % value1);
1541
1542 /* Otherwise do a div/mod hash */
1543
1544 else
1545   {
1546   total = total % (value1 * value2);
1547   s = string_sprintf("%lu/%lu", total/value2, total % value2);
1548   }
1549
1550 *len = Ustrlen(s);
1551 return s;
1552 }
1553
1554
1555
1556
1557
1558 /*************************************************
1559 *     Find the value of a header or headers      *
1560 *************************************************/
1561
1562 /* Multiple instances of the same header get concatenated, and this function
1563 can also return a concatenation of all the header lines. When concatenating
1564 specific headers that contain lists of addresses, a comma is inserted between
1565 them. Otherwise we use a straight concatenation. Because some messages can have
1566 pathologically large number of lines, there is a limit on the length that is
1567 returned.
1568
1569 Arguments:
1570   name          the name of the header, without the leading $header_ or $h_,
1571                 or NULL if a concatenation of all headers is required
1572   newsize       return the size of memory block that was obtained; may be NULL
1573                 if exists_only is TRUE
1574   flags         FH_EXISTS_ONLY
1575                   set if called from a def: test; don't need to build a string;
1576                   just return a string that is not "" and not "0" if the header
1577                   exists
1578                 FH_WANT_RAW
1579                   set if called for $rh_ or $rheader_ items; no processing,
1580                   other than concatenating, will be done on the header. Also used
1581                   for $message_headers_raw.
1582                 FH_WANT_LIST
1583                   Double colon chars in the content, and replace newline with
1584                   colon between each element when concatenating; returning a
1585                   colon-sep list (elements might contain newlines)
1586   charset       name of charset to translate MIME words to; used only if
1587                 want_raw is false; if NULL, no translation is done (this is
1588                 used for $bh_ and $bheader_)
1589
1590 Returns:        NULL if the header does not exist, else a pointer to a new
1591                 store block
1592 */
1593
1594 static uschar *
1595 find_header(uschar *name, int *newsize, unsigned flags, const uschar *charset)
1596 {
1597 BOOL found = !name;
1598 int len = name ? Ustrlen(name) : 0;
1599 BOOL comma = FALSE;
1600 gstring * g = NULL;
1601
1602 for (header_line * h = header_list; h; h = h->next)
1603   if (h->type != htype_old && h->text)  /* NULL => Received: placeholder */
1604     if (!name || (len <= h->slen && strncmpic(name, h->text, len) == 0))
1605       {
1606       uschar * s, * t;
1607       size_t inc;
1608
1609       if (flags & FH_EXISTS_ONLY)
1610         return US"1";  /* don't need actual string */
1611
1612       found = TRUE;
1613       s = h->text + len;                /* text to insert */
1614       if (!(flags & FH_WANT_RAW))       /* unless wanted raw, */
1615         Uskip_whitespace(&s);           /* remove leading white space */
1616       t = h->text + h->slen;            /* end-point */
1617
1618       /* Unless wanted raw, remove trailing whitespace, including the
1619       newline. */
1620
1621       if (flags & FH_WANT_LIST)
1622         while (t > s && t[-1] == '\n') t--;
1623       else if (!(flags & FH_WANT_RAW))
1624         {
1625         while (t > s && isspace(t[-1])) t--;
1626
1627         /* Set comma if handling a single header and it's one of those
1628         that contains an address list, except when asked for raw headers. Only
1629         need to do this once. */
1630
1631         if (name && !comma && Ustrchr("BCFRST", h->type)) comma = TRUE;
1632         }
1633
1634       /* Trim the header roughly if we're approaching limits */
1635       inc = t - s;
1636       if (gstring_length(g) + inc > header_insert_maxlen)
1637         inc = header_insert_maxlen - gstring_length(g);
1638
1639       /* For raw just copy the data; for a list, add the data as a colon-sep
1640       list-element; for comma-list add as an unchecked comma,newline sep
1641       list-elemment; for other nonraw add as an unchecked newline-sep list (we
1642       stripped trailing WS above including the newline). We ignore the potential
1643       expansion due to colon-doubling, just leaving the loop if the limit is met
1644       or exceeded. */
1645
1646       if (flags & FH_WANT_LIST)
1647         g = string_append_listele_n(g, ':', s, (unsigned)inc);
1648       else if (flags & FH_WANT_RAW)
1649         g = string_catn(g, s, (unsigned)inc);
1650       else if (inc > 0)
1651         g = string_append2_listele_n(g, comma ? US",\n" : US"\n",
1652           s, (unsigned)inc);
1653
1654       if (gstring_length(g) >= header_insert_maxlen) break;
1655       }
1656
1657 if (!found) return NULL;        /* No header found */
1658 if (!g) return US"";
1659
1660 /* That's all we do for raw header expansion. */
1661
1662 *newsize = g->size;
1663 if (flags & FH_WANT_RAW)
1664   return string_from_gstring(g);
1665
1666 /* Otherwise do RFC 2047 decoding, translating the charset if requested.
1667 The rfc2047_decode2() function can return an error with decoded data if the
1668 charset translation fails. If decoding fails, it returns NULL. */
1669
1670 else
1671   {
1672   uschar * error, * decoded = rfc2047_decode2(string_from_gstring(g),
1673     check_rfc2047_length, charset, '?', NULL, newsize, &error);
1674   if (error)
1675     DEBUG(D_any) debug_printf("*** error in RFC 2047 decoding: %s\n"
1676       "    input was: %s\n", error, g->s);
1677   return decoded ? decoded : string_from_gstring(g);
1678   }
1679 }
1680
1681
1682
1683
1684 /* Append a "local" element to an Authentication-Results: header
1685 if this was a non-smtp message.
1686 */
1687
1688 static gstring *
1689 authres_local(gstring * g, const uschar * sysname)
1690 {
1691 if (!f.authentication_local)
1692   return g;
1693 g = string_append(g, 3, US";\n\tlocal=pass (non-smtp, ", sysname, US")");
1694 if (authenticated_id) g = string_append(g, 2, " u=", authenticated_id);
1695 return g;
1696 }
1697
1698
1699 /* Append an "iprev" element to an Authentication-Results: header
1700 if we have attempted to get the calling host's name.
1701 */
1702
1703 static gstring *
1704 authres_iprev(gstring * g)
1705 {
1706 if (sender_host_name)
1707   g = string_append(g, 3, US";\n\tiprev=pass (", sender_host_name, US")");
1708 else if (host_lookup_deferred)
1709   g = string_cat(g, US";\n\tiprev=temperror");
1710 else if (host_lookup_failed)
1711   g = string_cat(g, US";\n\tiprev=fail");
1712 else
1713   return g;
1714
1715 if (sender_host_address)
1716   g = string_append(g, 2, US" smtp.remote-ip=", sender_host_address);
1717 return g;
1718 }
1719
1720
1721
1722 /*************************************************
1723 *               Return list of recipients        *
1724 *************************************************/
1725 /* A recipients list is available only during system message filtering,
1726 during ACL processing after DATA, and while expanding pipe commands
1727 generated from a system filter, but not elsewhere. */
1728
1729 static uschar *
1730 fn_recipients(void)
1731 {
1732 uschar * s;
1733 gstring * g = NULL;
1734
1735 if (!f.enable_dollar_recipients) return NULL;
1736
1737 for (int i = 0; i < recipients_count; i++)
1738   {
1739   s = recipients_list[i].address;
1740   g = string_append2_listele_n(g, US", ", s, Ustrlen(s));
1741   }
1742 return g ? g->s : NULL;
1743 }
1744
1745
1746 /*************************************************
1747 *               Return size of queue             *
1748 *************************************************/
1749 /* Ask the daemon for the queue size */
1750
1751 static uschar *
1752 fn_queue_size(void)
1753 {
1754 struct sockaddr_un sa_un = {.sun_family = AF_UNIX};
1755 uschar buf[16];
1756 int fd;
1757 ssize_t len;
1758 const uschar * where;
1759 uschar * sname;
1760
1761 if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
1762   {
1763   DEBUG(D_expand) debug_printf(" socket: %s\n", strerror(errno));
1764   return NULL;
1765   }
1766
1767 len = daemon_client_sockname(&sa_un, &sname);
1768
1769 if (bind(fd, (const struct sockaddr *)&sa_un, (socklen_t)len) < 0)
1770   { where = US"bind"; goto bad; }
1771
1772 #ifdef notdef
1773 debug_printf("local addr '%s%s'\n",
1774   *sa_un.sun_path ? "" : "@",
1775   sa_un.sun_path + (*sa_un.sun_path ? 0 : 1));
1776 #endif
1777
1778 len = daemon_notifier_sockname(&sa_un);
1779 if (connect(fd, (const struct sockaddr *)&sa_un, len) < 0)
1780   { where = US"connect"; goto bad2; }
1781
1782 buf[0] = NOTIFY_QUEUE_SIZE_REQ;
1783 if (send(fd, buf, 1, 0) < 0) { where = US"send"; goto bad; }
1784
1785 if (poll_one_fd(fd, POLLIN, 2 * 1000) != 1)
1786   {
1787   DEBUG(D_expand) debug_printf("no daemon response; using local evaluation\n");
1788   len = snprintf(CS buf, sizeof(buf), "%u", queue_count_cached());
1789   }
1790 else if ((len = recv(fd, buf, sizeof(buf), 0)) < 0)
1791   { where = US"recv"; goto bad2; }
1792
1793 close(fd);
1794 #ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1795 Uunlink(sname);
1796 #endif
1797 return string_copyn(buf, len);
1798
1799 bad2:
1800 #ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1801   Uunlink(sname);
1802 #endif
1803 bad:
1804   close(fd);
1805   DEBUG(D_expand) debug_printf(" %s: %s\n", where, strerror(errno));
1806   return NULL;
1807 }
1808
1809
1810 /*************************************************
1811 *               Find value of a variable         *
1812 *************************************************/
1813
1814 /* The table of variables is kept in alphabetic order, so we can search it
1815 using a binary chop. The "choplen" variable is nothing to do with the binary
1816 chop.
1817
1818 Arguments:
1819   name          the name of the variable being sought
1820   exists_only   TRUE if this is a def: test; passed on to find_header()
1821   skipping      TRUE => skip any processing evaluation; this is not the same as
1822                   exists_only because def: may test for values that are first
1823                   evaluated here
1824   newsize       pointer to an int which is initially zero; if the answer is in
1825                 a new memory buffer, *newsize is set to its size
1826
1827 Returns:        NULL if the variable does not exist, or
1828                 a pointer to the variable's contents, or
1829                 something non-NULL if exists_only is TRUE
1830 */
1831
1832 static const uschar *
1833 find_variable(uschar *name, BOOL exists_only, BOOL skipping, int *newsize)
1834 {
1835 var_entry * vp;
1836 uschar *s, *domain;
1837 uschar **ss;
1838 void * val;
1839
1840 /* Handle ACL variables, whose names are of the form acl_cxxx or acl_mxxx.
1841 Originally, xxx had to be a number in the range 0-9 (later 0-19), but from
1842 release 4.64 onwards arbitrary names are permitted, as long as the first 5
1843 characters are acl_c or acl_m and the sixth is either a digit or an underscore
1844 (this gave backwards compatibility at the changeover). There may be built-in
1845 variables whose names start acl_ but they should never start in this way. This
1846 slightly messy specification is a consequence of the history, needless to say.
1847
1848 If an ACL variable does not exist, treat it as empty, unless strict_acl_vars is
1849 set, in which case give an error. */
1850
1851 if ((Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) &&
1852      !isalpha(name[5]))
1853   {
1854   tree_node * node =
1855     tree_search(name[4] == 'c' ? acl_var_c : acl_var_m, name + 4);
1856   return node ? node->data.ptr : strict_acl_vars ? NULL : US"";
1857   }
1858 else if (Ustrncmp(name, "r_", 2) == 0)
1859   {
1860   tree_node * node = tree_search(router_var, name + 2);
1861   return node ? node->data.ptr : strict_acl_vars ? NULL : US"";
1862   }
1863
1864 /* Handle $auth<n>, $regex<n> variables. */
1865
1866 if (Ustrncmp(name, "auth", 4) == 0)
1867   {
1868   uschar *endptr;
1869   int n = Ustrtoul(name + 4, &endptr, 10);
1870   if (!*endptr && n != 0 && n <= AUTH_VARS)
1871     return auth_vars[n-1] ? auth_vars[n-1] : US"";
1872   }
1873 #ifdef WITH_CONTENT_SCAN
1874 else if (Ustrncmp(name, "regex", 5) == 0)
1875   {
1876   uschar *endptr;
1877   int n = Ustrtoul(name + 5, &endptr, 10);
1878   if (!*endptr && n != 0 && n <= REGEX_VARS)
1879     return regex_vars[n-1] ? regex_vars[n-1] : US"";
1880   }
1881 #endif
1882
1883 /* For all other variables, search the table */
1884
1885 if (!(vp = find_var_ent(name)))
1886   return NULL;          /* Unknown variable name */
1887
1888 /* Found an existing variable. If in skipping state, the value isn't needed,
1889 and we want to avoid processing (such as looking up the host name). */
1890
1891 if (skipping)
1892   return US"";
1893
1894 val = vp->value;
1895 switch (vp->type)
1896   {
1897   case vtype_filter_int:
1898     if (!f.filter_running) return NULL;
1899     /* Fall through */
1900     /* VVVVVVVVVVVV */
1901   case vtype_int:
1902     sprintf(CS var_buffer, "%d", *(int *)(val)); /* Integer */
1903     return var_buffer;
1904
1905   case vtype_ino:
1906     sprintf(CS var_buffer, "%ld", (long int)(*(ino_t *)(val))); /* Inode */
1907     return var_buffer;
1908
1909   case vtype_gid:
1910     sprintf(CS var_buffer, "%ld", (long int)(*(gid_t *)(val))); /* gid */
1911     return var_buffer;
1912
1913   case vtype_uid:
1914     sprintf(CS var_buffer, "%ld", (long int)(*(uid_t *)(val))); /* uid */
1915     return var_buffer;
1916
1917   case vtype_bool:
1918     sprintf(CS var_buffer, "%s", *(BOOL *)(val) ? "yes" : "no"); /* bool */
1919     return var_buffer;
1920
1921   case vtype_stringptr:                      /* Pointer to string */
1922     return (s = *((uschar **)(val))) ? s : US"";
1923
1924   case vtype_pid:
1925     sprintf(CS var_buffer, "%d", (int)getpid()); /* pid */
1926     return var_buffer;
1927
1928   case vtype_load_avg:
1929     sprintf(CS var_buffer, "%d", OS_GETLOADAVG()); /* load_average */
1930     return var_buffer;
1931
1932   case vtype_host_lookup:                    /* Lookup if not done so */
1933     if (  !sender_host_name && sender_host_address
1934        && !host_lookup_failed && host_name_lookup() == OK)
1935       host_build_sender_fullhost();
1936     return sender_host_name ? sender_host_name : US"";
1937
1938   case vtype_localpart:                      /* Get local part from address */
1939     if (!(s = *((uschar **)(val)))) return US"";
1940     if (!(domain = Ustrrchr(s, '@'))) return s;
1941     if (domain - s > sizeof(var_buffer) - 1)
1942       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than " SIZE_T_FMT
1943           " in string expansion", sizeof(var_buffer));
1944     return string_copyn(s, domain - s);
1945
1946   case vtype_domain:                         /* Get domain from address */
1947     if (!(s = *((uschar **)(val)))) return US"";
1948     domain = Ustrrchr(s, '@');
1949     return domain ? domain + 1 : US"";
1950
1951   case vtype_msgheaders:
1952     return find_header(NULL, newsize, exists_only ? FH_EXISTS_ONLY : 0, NULL);
1953
1954   case vtype_msgheaders_raw:
1955     return find_header(NULL, newsize,
1956                 exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW, NULL);
1957
1958   case vtype_msgbody:                        /* Pointer to msgbody string */
1959   case vtype_msgbody_end:                    /* Ditto, the end of the msg */
1960     ss = (uschar **)(val);
1961     if (!*ss && deliver_datafile >= 0)  /* Read body when needed */
1962       {
1963       uschar * body;
1964       off_t start_offset = SPOOL_DATA_START_OFFSET;
1965       int len = message_body_visible;
1966
1967       if (len > message_size) len = message_size;
1968       *ss = body = store_get(len+1, GET_TAINTED);
1969       body[0] = 0;
1970       if (vp->type == vtype_msgbody_end)
1971         {
1972         struct stat statbuf;
1973         if (fstat(deliver_datafile, &statbuf) == 0)
1974           {
1975           start_offset = statbuf.st_size - len;
1976           if (start_offset < SPOOL_DATA_START_OFFSET)
1977             start_offset = SPOOL_DATA_START_OFFSET;
1978           }
1979         }
1980       if (lseek(deliver_datafile, start_offset, SEEK_SET) < 0)
1981         log_write(0, LOG_MAIN|LOG_PANIC_DIE, "deliver_datafile lseek: %s",
1982           strerror(errno));
1983       if ((len = read(deliver_datafile, body, len)) > 0)
1984         {
1985         body[len] = 0;
1986         if (message_body_newlines)   /* Separate loops for efficiency */
1987           while (len > 0)
1988             { if (body[--len] == 0) body[len] = ' '; }
1989         else
1990           while (len > 0)
1991             { if (body[--len] == '\n' || body[len] == 0) body[len] = ' '; }
1992         }
1993       }
1994     return *ss ? *ss : US"";
1995
1996   case vtype_todbsdin:                       /* BSD inbox time of day */
1997     return tod_stamp(tod_bsdin);
1998
1999   case vtype_tode:                           /* Unix epoch time of day */
2000     return tod_stamp(tod_epoch);
2001
2002   case vtype_todel:                          /* Unix epoch/usec time of day */
2003     return tod_stamp(tod_epoch_l);
2004
2005   case vtype_todf:                           /* Full time of day */
2006     return tod_stamp(tod_full);
2007
2008   case vtype_todl:                           /* Log format time of day */
2009     return tod_stamp(tod_log_bare);            /* (without timezone) */
2010
2011   case vtype_todzone:                        /* Time zone offset only */
2012     return tod_stamp(tod_zone);
2013
2014   case vtype_todzulu:                        /* Zulu time */
2015     return tod_stamp(tod_zulu);
2016
2017   case vtype_todlf:                          /* Log file datestamp tod */
2018     return tod_stamp(tod_log_datestamp_daily);
2019
2020   case vtype_reply:                          /* Get reply address */
2021     s = find_header(US"reply-to:", newsize,
2022                 exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW,
2023                 headers_charset);
2024     if (s) Uskip_whitespace(&s);
2025     if (!s || !*s)
2026       {
2027       *newsize = 0;                            /* For the *s==0 case */
2028       s = find_header(US"from:", newsize,
2029                 exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW,
2030                 headers_charset);
2031       }
2032     if (s)
2033       {
2034       uschar *t;
2035       Uskip_whitespace(&s);
2036       for (t = s; *t; t++) if (*t == '\n') *t = ' ';
2037       while (t > s && isspace(t[-1])) t--;
2038       *t = 0;
2039       }
2040     return s ? s : US"";
2041
2042   case vtype_string_func:
2043     {
2044     stringptr_fn_t * fn = (stringptr_fn_t *) val;
2045     uschar* s = fn();
2046     return s ? s : US"";
2047     }
2048
2049   case vtype_pspace:
2050     {
2051     int inodes;
2052     sprintf(CS var_buffer, PR_EXIM_ARITH,
2053       receive_statvfs(val == (void *)TRUE, &inodes));
2054     }
2055   return var_buffer;
2056
2057   case vtype_pinodes:
2058     {
2059     int inodes;
2060     (void) receive_statvfs(val == (void *)TRUE, &inodes);
2061     sprintf(CS var_buffer, "%d", inodes);
2062     }
2063   return var_buffer;
2064
2065   case vtype_cert:
2066     return *(void **)val ? US"<cert>" : US"";
2067
2068 #ifndef DISABLE_DKIM
2069   case vtype_dkim:
2070     return dkim_exim_expand_query((int)(long)val);
2071 #endif
2072
2073   }
2074
2075 return NULL;  /* Unknown variable. Silences static checkers. */
2076 }
2077
2078
2079
2080
2081 void
2082 modify_variable(uschar *name, void * value)
2083 {
2084 var_entry * vp;
2085 if ((vp = find_var_ent(name))) vp->value = value;
2086 return;          /* Unknown variable name, fail silently */
2087 }
2088
2089
2090
2091
2092
2093
2094 /*************************************************
2095 *           Read and expand substrings           *
2096 *************************************************/
2097
2098 /* This function is called to read and expand argument substrings for various
2099 expansion items. Some have a minimum requirement that is less than the maximum;
2100 in these cases, the first non-present one is set to NULL.
2101
2102 Arguments:
2103   sub        points to vector of pointers to set
2104   n          maximum number of substrings
2105   m          minimum required
2106   sptr       points to current string pointer
2107   flags
2108    skipping   the skipping flag
2109   check_end  if TRUE, check for final '}'
2110   name       name of item, for error message
2111   resetok    if not NULL, pointer to flag - write FALSE if unsafe to reset
2112              the store
2113   textonly_p if not NULL, pointer to bitmask of which subs were text-only
2114              (did not change when expended)
2115
2116 Returns:     -1 OK; string pointer updated, but in "skipping" mode
2117              0 OK; string pointer updated
2118              1 curly bracketing error (too few arguments)
2119              2 too many arguments (only if check_end is set); message set
2120              3 other error (expansion failure)
2121 */
2122
2123 static int
2124 read_subs(uschar ** sub, int n, int m, const uschar ** sptr, esi_flags flags,
2125   BOOL check_end, uschar * name, BOOL * resetok, unsigned * textonly_p)
2126 {
2127 const uschar * s = *sptr;
2128 unsigned textonly_l = 0;
2129
2130 Uskip_whitespace(&s);
2131 for (int i = 0; i < n; i++)
2132   {
2133   BOOL textonly;
2134   if (*s != '{')
2135     {
2136     if (i < m)
2137       {
2138       expand_string_message = string_sprintf("Not enough arguments for '%s' "
2139         "(min is %d)", name, m);
2140       return 1;
2141       }
2142     sub[i] = NULL;
2143     break;
2144     }
2145   if (!(sub[i] = expand_string_internal(s+1,
2146           ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags & ESI_SKIPPING, &s, resetok,
2147           textonly_p ? &textonly : NULL)))
2148     return 3;
2149   if (*s++ != '}') return 1;
2150   if (textonly_p && textonly) textonly_l |= BIT(i);
2151   Uskip_whitespace(&s);
2152   }                                             /*{*/
2153 if (check_end && *s++ != '}')
2154   {
2155   if (s[-1] == '{')
2156     {
2157     expand_string_message = string_sprintf("Too many arguments for '%s' "
2158       "(max is %d)", name, n);
2159     return 2;
2160     }
2161   expand_string_message = string_sprintf("missing '}' after '%s'", name);
2162   return 1;
2163   }
2164
2165 if (textonly_p) *textonly_p = textonly_l;
2166 *sptr = s;
2167 return flags & ESI_SKIPPING ? -1 : 0;
2168 }
2169
2170
2171
2172
2173 /*************************************************
2174 *     Elaborate message for bad variable         *
2175 *************************************************/
2176
2177 /* For the "unknown variable" message, take a look at the variable's name, and
2178 give additional information about possible ACL variables. The extra information
2179 is added on to expand_string_message.
2180
2181 Argument:   the name of the variable
2182 Returns:    nothing
2183 */
2184
2185 static void
2186 check_variable_error_message(uschar *name)
2187 {
2188 if (Ustrncmp(name, "acl_", 4) == 0)
2189   expand_string_message = string_sprintf("%s (%s)", expand_string_message,
2190     (name[4] == 'c' || name[4] == 'm')?
2191       (isalpha(name[5])?
2192         US"6th character of a user-defined ACL variable must be a digit or underscore" :
2193         US"strict_acl_vars is set"    /* Syntax is OK, it has to be this */
2194       ) :
2195       US"user-defined ACL variables must start acl_c or acl_m");
2196 }
2197
2198
2199
2200 /*
2201 Load args from sub array to globals, and call acl_check().
2202 Sub array will be corrupted on return.
2203
2204 Returns:       OK         access is granted by an ACCEPT verb
2205                DISCARD    access is (apparently) granted by a DISCARD verb
2206                FAIL       access is denied
2207                FAIL_DROP  access is denied; drop the connection
2208                DEFER      can't tell at the moment
2209                ERROR      disaster
2210 */
2211 static int
2212 eval_acl(uschar ** sub, int nsub, uschar ** user_msgp)
2213 {
2214 int i;
2215 int sav_narg = acl_narg;
2216 int ret;
2217 uschar * dummy_logmsg;
2218 extern int acl_where;
2219
2220 if(--nsub > nelem(acl_arg)) nsub = nelem(acl_arg);
2221 for (i = 0; i < nsub && sub[i+1]; i++)
2222   {
2223   uschar * tmp = acl_arg[i];
2224   acl_arg[i] = sub[i+1];        /* place callers args in the globals */
2225   sub[i+1] = tmp;               /* stash the old args using our caller's storage */
2226   }
2227 acl_narg = i;
2228 while (i < nsub)
2229   {
2230   sub[i+1] = acl_arg[i];
2231   acl_arg[i++] = NULL;
2232   }
2233
2234 DEBUG(D_expand)
2235   debug_printf_indent("expanding: acl: %s  arg: %s%s\n",
2236     sub[0],
2237     acl_narg>0 ? acl_arg[0] : US"<none>",
2238     acl_narg>1 ? " +more"   : "");
2239
2240 ret = acl_eval(acl_where, sub[0], user_msgp, &dummy_logmsg);
2241
2242 for (i = 0; i < nsub; i++)
2243   acl_arg[i] = sub[i+1];        /* restore old args */
2244 acl_narg = sav_narg;
2245
2246 return ret;
2247 }
2248
2249
2250
2251
2252 /* Return pointer to dewrapped string, with enclosing specified chars removed.
2253 The given string is modified on return.  Leading whitespace is skipped while
2254 looking for the opening wrap character, then the rest is scanned for the trailing
2255 (non-escaped) wrap character.  A backslash in the string will act as an escape.
2256
2257 A nul is written over the trailing wrap, and a pointer to the char after the
2258 leading wrap is returned.
2259
2260 Arguments:
2261   s     String for de-wrapping
2262   wrap  Two-char string, the first being the opener, second the closer wrapping
2263         character
2264 Return:
2265   Pointer to de-wrapped string, or NULL on error (with expand_string_message set).
2266 */
2267
2268 static uschar *
2269 dewrap(uschar * s, const uschar * wrap)
2270 {
2271 uschar * p = s;
2272 unsigned depth = 0;
2273 BOOL quotesmode = wrap[0] == wrap[1];
2274
2275 if (Uskip_whitespace(&p) == *wrap)
2276   {
2277   s = ++p;
2278   wrap++;
2279   while (*p)
2280     {
2281     if (*p == '\\') p++;
2282     else if (!quotesmode && *p == wrap[-1]) depth++;
2283     else if (*p == *wrap)
2284       if (depth == 0)
2285         {
2286         *p = '\0';
2287         return s;
2288         }
2289       else
2290         depth--;
2291     p++;
2292     }
2293   }
2294 expand_string_message = string_sprintf("missing '%c'", *wrap);
2295 return NULL;
2296 }
2297
2298
2299 /* Pull off the leading array or object element, returning
2300 a copy in an allocated string.  Update the list pointer.
2301
2302 The element may itself be an abject or array.
2303 Return NULL when the list is empty.
2304 */
2305
2306 static uschar *
2307 json_nextinlist(const uschar ** list)
2308 {
2309 unsigned array_depth = 0, object_depth = 0;
2310 const uschar * s = *list, * item;
2311
2312 skip_whitespace(&s);
2313
2314 for (item = s;
2315      *s && (*s != ',' || array_depth != 0 || object_depth != 0);
2316      s++)
2317   switch (*s)
2318     {
2319     case '[': array_depth++; break;
2320     case ']': array_depth--; break;
2321     case '{': object_depth++; break;
2322     case '}': object_depth--; break;
2323     }
2324 *list = *s ? s+1 : s;
2325 if (item == s) return NULL;
2326 item = string_copyn(item, s - item);
2327 DEBUG(D_expand) debug_printf_indent("  json ele: '%s'\n", item);
2328 return US item;
2329 }
2330
2331
2332
2333 /************************************************/
2334 /*  Return offset in ops table, or -1 if not found.
2335 Repoint to just after the operator in the string.
2336
2337 Argument:
2338  ss     string representation of operator
2339  opname split-out operator name
2340 */
2341
2342 static int
2343 identify_operator(const uschar ** ss, uschar ** opname)
2344 {
2345 const uschar * s = *ss;
2346 uschar name[256];
2347
2348 /* Numeric comparisons are symbolic */
2349
2350 if (*s == '=' || *s == '>' || *s == '<')
2351   {
2352   int p = 0;
2353   name[p++] = *s++;
2354   if (*s == '=')
2355     {
2356     name[p++] = '=';
2357     s++;
2358     }
2359   name[p] = 0;
2360   }
2361
2362 /* All other conditions are named */
2363
2364 else
2365   s = read_name(name, sizeof(name), s, US"_");
2366 *ss = s;
2367
2368 /* If we haven't read a name, it means some non-alpha character is first. */
2369
2370 if (!name[0])
2371   {
2372   expand_string_message = string_sprintf("condition name expected, "
2373     "but found \"%.16s\"", s);
2374   return -1;
2375   }
2376 if (opname)
2377   *opname = string_copy(name);
2378
2379 return chop_match(name, cond_table, nelem(cond_table));
2380 }
2381
2382
2383 /*************************************************
2384 *    Handle MD5 or SHA-1 computation for HMAC    *
2385 *************************************************/
2386
2387 /* These are some wrapping functions that enable the HMAC code to be a bit
2388 cleaner. A good compiler will spot the tail recursion.
2389
2390 Arguments:
2391   type         HMAC_MD5 or HMAC_SHA1
2392   remaining    are as for the cryptographic hash functions
2393
2394 Returns:       nothing
2395 */
2396
2397 static void
2398 chash_start(int type, void * base)
2399 {
2400 if (type == HMAC_MD5)
2401   md5_start((md5 *)base);
2402 else
2403   sha1_start((hctx *)base);
2404 }
2405
2406 static void
2407 chash_mid(int type, void * base, const uschar * string)
2408 {
2409 if (type == HMAC_MD5)
2410   md5_mid((md5 *)base, string);
2411 else
2412   sha1_mid((hctx *)base, string);
2413 }
2414
2415 static void
2416 chash_end(int type, void * base, const uschar * string, int length,
2417   uschar * digest)
2418 {
2419 if (type == HMAC_MD5)
2420   md5_end((md5 *)base, string, length, digest);
2421 else
2422   sha1_end((hctx *)base, string, length, digest);
2423 }
2424
2425
2426
2427
2428 #ifdef SUPPORT_SRS
2429 /* Do an hmac_md5.  The result is _not_ nul-terminated, and is sized as
2430 the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
2431
2432 Arguments:
2433         key     encoding key, nul-terminated
2434         src     data to be hashed, nul-terminated
2435         buf     output buffer
2436         len     size of output buffer
2437 */
2438
2439 static void
2440 hmac_md5(const uschar * key, const uschar * src, uschar * buf, unsigned len)
2441 {
2442 md5 md5_base;
2443 const uschar * keyptr;
2444 uschar * p;
2445 unsigned int keylen;
2446
2447 #define MD5_HASHLEN      16
2448 #define MD5_HASHBLOCKLEN 64
2449
2450 uschar keyhash[MD5_HASHLEN];
2451 uschar innerhash[MD5_HASHLEN];
2452 uschar finalhash[MD5_HASHLEN];
2453 uschar innerkey[MD5_HASHBLOCKLEN];
2454 uschar outerkey[MD5_HASHBLOCKLEN];
2455
2456 keyptr = key;
2457 keylen = Ustrlen(keyptr);
2458
2459 /* If the key is longer than the hash block length, then hash the key
2460 first */
2461
2462 if (keylen > MD5_HASHBLOCKLEN)
2463   {
2464   chash_start(HMAC_MD5, &md5_base);
2465   chash_end(HMAC_MD5, &md5_base, keyptr, keylen, keyhash);
2466   keyptr = keyhash;
2467   keylen = MD5_HASHLEN;
2468   }
2469
2470 /* Now make the inner and outer key values */
2471
2472 memset(innerkey, 0x36, MD5_HASHBLOCKLEN);
2473 memset(outerkey, 0x5c, MD5_HASHBLOCKLEN);
2474
2475 for (int i = 0; i < keylen; i++)
2476   {
2477   innerkey[i] ^= keyptr[i];
2478   outerkey[i] ^= keyptr[i];
2479   }
2480
2481 /* Now do the hashes */
2482
2483 chash_start(HMAC_MD5, &md5_base);
2484 chash_mid(HMAC_MD5, &md5_base, innerkey);
2485 chash_end(HMAC_MD5, &md5_base, src, Ustrlen(src), innerhash);
2486
2487 chash_start(HMAC_MD5, &md5_base);
2488 chash_mid(HMAC_MD5, &md5_base, outerkey);
2489 chash_end(HMAC_MD5, &md5_base, innerhash, MD5_HASHLEN, finalhash);
2490
2491 /* Encode the final hash as a hex string, limited by output buffer size */
2492
2493 p = buf;
2494 for (int i = 0, j = len; i < MD5_HASHLEN; i++)
2495   {
2496   if (j-- <= 0) break;
2497   *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
2498   if (j-- <= 0) break;
2499   *p++ = hex_digits[finalhash[i] & 0x0f];
2500   }
2501 return;
2502 }
2503 #endif /*SUPPORT_SRS*/
2504
2505
2506 /*************************************************
2507 *        Read and evaluate a condition           *
2508 *************************************************/
2509
2510 /*
2511 Arguments:
2512   s        points to the start of the condition text
2513   resetok  points to a BOOL which is written false if it is unsafe to
2514            free memory. Certain condition types (acl) may have side-effect
2515            allocation which must be preserved.
2516   yield    points to a BOOL to hold the result of the condition test;
2517            if NULL, we are just reading through a condition that is
2518            part of an "or" combination to check syntax, or in a state
2519            where the answer isn't required
2520
2521 Returns:   a pointer to the first character after the condition, or
2522            NULL after an error
2523 */
2524
2525 static const uschar *
2526 eval_condition(const uschar * s, BOOL * resetok, BOOL * yield)
2527 {
2528 BOOL testfor = TRUE;
2529 BOOL tempcond, combined_cond;
2530 BOOL * subcondptr;
2531 BOOL sub2_honour_dollar = TRUE;
2532 BOOL is_forany, is_json, is_jsons;
2533 int rc, cond_type;
2534 int_eximarith_t num[2];
2535 struct stat statbuf;
2536 uschar * opname;
2537 uschar name[256];
2538 const uschar * sub[10];
2539 unsigned sub_textonly = 0;
2540
2541 for (;;)
2542   if (Uskip_whitespace(&s) == '!') { testfor = !testfor; s++; } else break;
2543
2544 switch(cond_type = identify_operator(&s, &opname))
2545   {
2546   /* def: tests for a non-empty variable, or for the existence of a header. If
2547   yield == NULL we are in a skipping state, and don't care about the answer. */
2548
2549   case ECOND_DEF:
2550     {
2551     const uschar * t;
2552
2553     if (*s != ':')
2554       {
2555       expand_string_message = US"\":\" expected after \"def\"";
2556       return NULL;
2557       }
2558
2559     s = read_name(name, sizeof(name), s+1, US"_");
2560
2561     /* Test for a header's existence. If the name contains a closing brace
2562     character, this may be a user error where the terminating colon has been
2563     omitted. Set a flag to adjust a subsequent error message in this case. */
2564
2565     if (  ( *(t = name) == 'h'
2566           || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
2567           )
2568        && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
2569        )
2570       {
2571       s = read_header_name(name, sizeof(name), s);
2572       /* {-for-text-editors */
2573       if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
2574       if (yield) *yield =
2575         (find_header(name, NULL, FH_EXISTS_ONLY, NULL) != NULL) == testfor;
2576       }
2577
2578     /* Test for a variable's having a non-empty value. A non-existent variable
2579     causes an expansion failure. */
2580
2581     else
2582       {
2583       if (!(t = find_variable(name, TRUE, yield == NULL, NULL)))
2584         {
2585         expand_string_message = name[0]
2586           ? string_sprintf("unknown variable \"%s\" after \"def:\"", name)
2587           : US"variable name omitted after \"def:\"";
2588         check_variable_error_message(name);
2589         return NULL;
2590         }
2591       if (yield) *yield = (t[0] != 0) == testfor;
2592       }
2593
2594     return s;
2595     }
2596
2597
2598   /* first_delivery tests for first delivery attempt */
2599
2600   case ECOND_FIRST_DELIVERY:
2601   if (yield) *yield = f.deliver_firsttime == testfor;
2602   return s;
2603
2604
2605   /* queue_running tests for any process started by a queue runner */
2606
2607   case ECOND_QUEUE_RUNNING:
2608   if (yield) *yield = (queue_run_pid != (pid_t)0) == testfor;
2609   return s;
2610
2611
2612   /* exists:  tests for file existence
2613        isip:  tests for any IP address
2614       isip4:  tests for an IPv4 address
2615       isip6:  tests for an IPv6 address
2616         pam:  does PAM authentication
2617      radius:  does RADIUS authentication
2618    ldapauth:  does LDAP authentication
2619     pwcheck:  does Cyrus SASL pwcheck authentication
2620   */
2621
2622   case ECOND_EXISTS:
2623   case ECOND_ISIP:
2624   case ECOND_ISIP4:
2625   case ECOND_ISIP6:
2626   case ECOND_PAM:
2627   case ECOND_RADIUS:
2628   case ECOND_LDAPAUTH:
2629   case ECOND_PWCHECK:
2630
2631   if (Uskip_whitespace(&s) != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2632
2633    {
2634     BOOL textonly;
2635     sub[0] = expand_string_internal(s+1,
2636       ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | (yield ? ESI_NOFLAGS : ESI_SKIPPING),
2637       &s, resetok, &textonly);
2638     if (!sub[0]) return NULL;
2639     if (textonly) sub_textonly |= BIT(0);
2640    }
2641   /* {-for-text-editors */
2642   if (*s++ != '}') goto COND_FAILED_CURLY_END;
2643
2644   if (!yield) return s;   /* No need to run the test if skipping */
2645
2646   switch(cond_type)
2647     {
2648     case ECOND_EXISTS:
2649     if ((expand_forbid & RDO_EXISTS) != 0)
2650       {
2651       expand_string_message = US"File existence tests are not permitted";
2652       return NULL;
2653       }
2654     *yield = (Ustat(sub[0], &statbuf) == 0) == testfor;
2655     break;
2656
2657     case ECOND_ISIP:
2658     case ECOND_ISIP4:
2659     case ECOND_ISIP6:
2660     rc = string_is_ip_address(sub[0], NULL);
2661     *yield = ((cond_type == ECOND_ISIP)? (rc != 0) :
2662              (cond_type == ECOND_ISIP4)? (rc == 4) : (rc == 6)) == testfor;
2663     break;
2664
2665     /* Various authentication tests - all optionally compiled */
2666
2667     case ECOND_PAM:
2668     #ifdef SUPPORT_PAM
2669     rc = auth_call_pam(sub[0], &expand_string_message);
2670     goto END_AUTH;
2671     #else
2672     goto COND_FAILED_NOT_COMPILED;
2673     #endif  /* SUPPORT_PAM */
2674
2675     case ECOND_RADIUS:
2676     #ifdef RADIUS_CONFIG_FILE
2677     rc = auth_call_radius(sub[0], &expand_string_message);
2678     goto END_AUTH;
2679     #else
2680     goto COND_FAILED_NOT_COMPILED;
2681     #endif  /* RADIUS_CONFIG_FILE */
2682
2683     case ECOND_LDAPAUTH:
2684     #ifdef LOOKUP_LDAP
2685       {
2686       /* Just to keep the interface the same */
2687       BOOL do_cache;
2688       int old_pool = store_pool;
2689       store_pool = POOL_SEARCH;
2690       rc = eldapauth_find((void *)(-1), NULL, sub[0], Ustrlen(sub[0]), NULL,
2691         &expand_string_message, &do_cache);
2692       store_pool = old_pool;
2693       }
2694     goto END_AUTH;
2695     #else
2696     goto COND_FAILED_NOT_COMPILED;
2697     #endif  /* LOOKUP_LDAP */
2698
2699     case ECOND_PWCHECK:
2700     #ifdef CYRUS_PWCHECK_SOCKET
2701     rc = auth_call_pwcheck(sub[0], &expand_string_message);
2702     goto END_AUTH;
2703     #else
2704     goto COND_FAILED_NOT_COMPILED;
2705     #endif  /* CYRUS_PWCHECK_SOCKET */
2706
2707     #if defined(SUPPORT_PAM) || defined(RADIUS_CONFIG_FILE) || \
2708         defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET)
2709     END_AUTH:
2710     if (rc == ERROR || rc == DEFER) return NULL;
2711     *yield = (rc == OK) == testfor;
2712     #endif
2713     }
2714   return s;
2715
2716
2717   /* call ACL (in a conditional context).  Accept true, deny false.
2718   Defer is a forced-fail.  Anything set by message= goes to $value.
2719   Up to ten parameters are used; we use the braces round the name+args
2720   like the saslauthd condition does, to permit a variable number of args.
2721   See also the expansion-item version EITEM_ACL and the traditional
2722   acl modifier ACLC_ACL.
2723   Since the ACL may allocate new global variables, tell our caller to not
2724   reclaim memory.
2725   */
2726
2727   case ECOND_ACL:
2728     /* ${if acl {{name}{arg1}{arg2}...}  {yes}{no}} */
2729     {
2730     uschar *sub[10];
2731     uschar *user_msg;
2732     BOOL cond = FALSE;
2733
2734     Uskip_whitespace(&s);
2735     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /*}*/
2736
2737     switch(read_subs(sub, nelem(sub), 1, &s,
2738         yield ? ESI_NOFLAGS : ESI_SKIPPING, TRUE, name, resetok, NULL))
2739       {
2740       case 1: expand_string_message = US"too few arguments or bracketing "
2741         "error for acl";
2742       case 2:
2743       case 3: return NULL;
2744       }
2745
2746     if (yield)
2747       {
2748       int rc;
2749       *resetok = FALSE; /* eval_acl() might allocate; do not reclaim */
2750       switch(rc = eval_acl(sub, nelem(sub), &user_msg))
2751         {
2752         case OK:
2753           cond = TRUE;
2754         case FAIL:
2755           lookup_value = NULL;
2756           if (user_msg)
2757             lookup_value = string_copy(user_msg);
2758           *yield = cond == testfor;
2759           break;
2760
2761         case DEFER:
2762           f.expand_string_forcedfail = TRUE;
2763           /*FALLTHROUGH*/
2764         default:
2765           expand_string_message = string_sprintf("%s from acl \"%s\"",
2766             rc_names[rc], sub[0]);
2767           return NULL;
2768         }
2769       }
2770     return s;
2771     }
2772
2773
2774   /* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
2775
2776      ${if saslauthd {{username}{password}{service}{realm}}  {yes}{no}}
2777
2778   However, the last two are optional. That is why the whole set is enclosed
2779   in their own set of braces. */
2780
2781   case ECOND_SASLAUTHD:
2782 #ifndef CYRUS_SASLAUTHD_SOCKET
2783     goto COND_FAILED_NOT_COMPILED;
2784 #else
2785     {
2786     uschar *sub[4];
2787     Uskip_whitespace(&s);
2788     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
2789     switch(read_subs(sub, nelem(sub), 2, &s,
2790         yield ? ESI_NOFLAGS : ESI_SKIPPING, TRUE, name, resetok, NULL))
2791       {
2792       case 1: expand_string_message = US"too few arguments or bracketing "
2793         "error for saslauthd";
2794       case 2:
2795       case 3: return NULL;
2796       }
2797     if (!sub[2]) sub[3] = NULL;  /* realm if no service */
2798     if (yield)
2799       {
2800       int rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
2801         &expand_string_message);
2802       if (rc == ERROR || rc == DEFER) return NULL;
2803       *yield = (rc == OK) == testfor;
2804       }
2805     return s;
2806     }
2807 #endif /* CYRUS_SASLAUTHD_SOCKET */
2808
2809
2810   /* symbolic operators for numeric and string comparison, and a number of
2811   other operators, all requiring two arguments.
2812
2813   crypteq:           encrypts plaintext and compares against an encrypted text,
2814                        using crypt(), crypt16(), MD5 or SHA-1
2815   inlist/inlisti:    checks if first argument is in the list of the second
2816   match:             does a regular expression match and sets up the numerical
2817                        variables if it succeeds
2818   match_address:     matches in an address list
2819   match_domain:      matches in a domain list
2820   match_ip:          matches a host list that is restricted to IP addresses
2821   match_local_part:  matches in a local part list
2822   */
2823
2824   case ECOND_MATCH_ADDRESS:
2825   case ECOND_MATCH_DOMAIN:
2826   case ECOND_MATCH_IP:
2827   case ECOND_MATCH_LOCAL_PART:
2828 #ifndef EXPAND_LISTMATCH_RHS
2829     sub2_honour_dollar = FALSE;
2830 #endif
2831     /* FALLTHROUGH */
2832
2833   case ECOND_CRYPTEQ:
2834   case ECOND_INLIST:
2835   case ECOND_INLISTI:
2836   case ECOND_MATCH:
2837
2838   case ECOND_NUM_L:     /* Numerical comparisons */
2839   case ECOND_NUM_LE:
2840   case ECOND_NUM_E:
2841   case ECOND_NUM_EE:
2842   case ECOND_NUM_G:
2843   case ECOND_NUM_GE:
2844
2845   case ECOND_STR_LT:    /* String comparisons */
2846   case ECOND_STR_LTI:
2847   case ECOND_STR_LE:
2848   case ECOND_STR_LEI:
2849   case ECOND_STR_EQ:
2850   case ECOND_STR_EQI:
2851   case ECOND_STR_GT:
2852   case ECOND_STR_GTI:
2853   case ECOND_STR_GE:
2854   case ECOND_STR_GEI:
2855
2856   for (int i = 0; i < 2; i++)
2857     {
2858     BOOL textonly;
2859     /* Sometimes, we don't expand substrings; too many insecure configurations
2860     created using match_address{}{} and friends, where the second param
2861     includes information from untrustworthy sources. */
2862     /*XXX is this moot given taint-tracking? */
2863
2864     esi_flags flags = ESI_BRACE_ENDS;
2865
2866     if (!(i > 0 && !sub2_honour_dollar)) flags |= ESI_HONOR_DOLLAR;
2867     if (!yield) flags |= ESI_SKIPPING;
2868
2869     if (Uskip_whitespace(&s) != '{')
2870       {
2871       if (i == 0) goto COND_FAILED_CURLY_START;
2872       expand_string_message = string_sprintf("missing 2nd string in {} "
2873         "after \"%s\"", opname);
2874       return NULL;
2875       }
2876     if (!(sub[i] = expand_string_internal(s+1, flags, &s, resetok, &textonly)))
2877       return NULL;
2878     if (textonly) sub_textonly |= BIT(i);
2879     DEBUG(D_expand) if (i == 1 && !sub2_honour_dollar && Ustrchr(sub[1], '$'))
2880       debug_printf_indent("WARNING: the second arg is NOT expanded,"
2881                         " for security reasons\n");
2882     if (*s++ != '}') goto COND_FAILED_CURLY_END;
2883
2884     /* Convert to numerical if required; we know that the names of all the
2885     conditions that compare numbers do not start with a letter. This just saves
2886     checking for them individually. */
2887
2888     if (!isalpha(opname[0]) && yield)
2889       if (sub[i][0] == 0)
2890         {
2891         num[i] = 0;
2892         DEBUG(D_expand)
2893           debug_printf_indent("empty string cast to zero for numerical comparison\n");
2894         }
2895       else
2896         {
2897         num[i] = expanded_string_integer(sub[i], FALSE);
2898         if (expand_string_message) return NULL;
2899         }
2900     }
2901
2902   /* Result not required */
2903
2904   if (!yield) return s;
2905
2906   /* Do an appropriate comparison */
2907
2908   switch(cond_type)
2909     {
2910     case ECOND_NUM_E:
2911     case ECOND_NUM_EE:
2912       tempcond = (num[0] == num[1]); break;
2913
2914     case ECOND_NUM_G:
2915       tempcond = (num[0] > num[1]); break;
2916
2917     case ECOND_NUM_GE:
2918       tempcond = (num[0] >= num[1]); break;
2919
2920     case ECOND_NUM_L:
2921       tempcond = (num[0] < num[1]); break;
2922
2923     case ECOND_NUM_LE:
2924       tempcond = (num[0] <= num[1]); break;
2925
2926     case ECOND_STR_LT:
2927       tempcond = (Ustrcmp(sub[0], sub[1]) < 0); break;
2928
2929     case ECOND_STR_LTI:
2930       tempcond = (strcmpic(sub[0], sub[1]) < 0); break;
2931
2932     case ECOND_STR_LE:
2933       tempcond = (Ustrcmp(sub[0], sub[1]) <= 0); break;
2934
2935     case ECOND_STR_LEI:
2936       tempcond = (strcmpic(sub[0], sub[1]) <= 0); break;
2937
2938     case ECOND_STR_EQ:
2939       tempcond = (Ustrcmp(sub[0], sub[1]) == 0); break;
2940
2941     case ECOND_STR_EQI:
2942       tempcond = (strcmpic(sub[0], sub[1]) == 0); break;
2943
2944     case ECOND_STR_GT:
2945       tempcond = (Ustrcmp(sub[0], sub[1]) > 0); break;
2946
2947     case ECOND_STR_GTI:
2948       tempcond = (strcmpic(sub[0], sub[1]) > 0); break;
2949
2950     case ECOND_STR_GE:
2951       tempcond = (Ustrcmp(sub[0], sub[1]) >= 0); break;
2952
2953     case ECOND_STR_GEI:
2954       tempcond = (strcmpic(sub[0], sub[1]) >= 0); break;
2955
2956     case ECOND_MATCH:   /* Regular expression match */
2957       {
2958       const pcre2_code * re = regex_compile(sub[1],
2959                   sub_textonly & BIT(1) ? MCS_CACHEABLE : MCS_NOFLAGS,
2960                   &expand_string_message, pcre_gen_cmp_ctx);
2961       if (!re)
2962         return NULL;
2963
2964       tempcond = regex_match_and_setup(re, sub[0], 0, -1);
2965       break;
2966       }
2967
2968     case ECOND_MATCH_ADDRESS:  /* Match in an address list */
2969       rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0,
2970                               CUSS &lookup_value);
2971       goto MATCHED_SOMETHING;
2972
2973     case ECOND_MATCH_DOMAIN:   /* Match in a domain list */
2974       rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
2975         MCL_DOMAIN + MCL_NOEXPAND, TRUE, CUSS &lookup_value);
2976       goto MATCHED_SOMETHING;
2977
2978     case ECOND_MATCH_IP:       /* Match IP address in a host list */
2979       if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) == 0)
2980         {
2981         expand_string_message = string_sprintf("\"%s\" is not an IP address",
2982           sub[0]);
2983         return NULL;
2984         }
2985       else
2986         {
2987         unsigned int *nullcache = NULL;
2988         check_host_block cb;
2989
2990         cb.host_name = US"";
2991         cb.host_address = sub[0];
2992
2993         /* If the host address starts off ::ffff: it is an IPv6 address in
2994         IPv4-compatible mode. Find the IPv4 part for checking against IPv4
2995         addresses. */
2996
2997         cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
2998           cb.host_address + 7 : cb.host_address;
2999
3000         rc = match_check_list(
3001                &sub[1],                   /* the list */
3002                0,                         /* separator character */
3003                &hostlist_anchor,          /* anchor pointer */
3004                &nullcache,                /* cache pointer */
3005                check_host,                /* function for testing */
3006                &cb,                       /* argument for function */
3007                MCL_HOST,                  /* type of check */
3008                sub[0],                    /* text for debugging */
3009                CUSS &lookup_value);       /* where to pass back data */
3010         }
3011       goto MATCHED_SOMETHING;
3012
3013     case ECOND_MATCH_LOCAL_PART:
3014       rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
3015         MCL_LOCALPART + MCL_NOEXPAND, TRUE, CUSS &lookup_value);
3016       /* Fall through */
3017       /* VVVVVVVVVVVV */
3018       MATCHED_SOMETHING:
3019       switch(rc)
3020         {
3021         case OK:   tempcond = TRUE;  break;
3022         case FAIL: tempcond = FALSE; break;
3023
3024         case DEFER:
3025           expand_string_message = string_sprintf("unable to complete match "
3026             "against \"%s\": %s", sub[1], search_error_message);
3027           return NULL;
3028         }
3029
3030       break;
3031
3032     /* Various "encrypted" comparisons. If the second string starts with
3033     "{" then an encryption type is given. Default to crypt() or crypt16()
3034     (build-time choice). */
3035     /* }-for-text-editors */
3036
3037     case ECOND_CRYPTEQ:
3038     #ifndef SUPPORT_CRYPTEQ
3039       goto COND_FAILED_NOT_COMPILED;
3040     #else
3041       if (strncmpic(sub[1], US"{md5}", 5) == 0)
3042         {
3043         int sublen = Ustrlen(sub[1]+5);
3044         md5 base;
3045         uschar digest[16];
3046
3047         md5_start(&base);
3048         md5_end(&base, sub[0], Ustrlen(sub[0]), digest);
3049
3050         /* If the length that we are comparing against is 24, the MD5 digest
3051         is expressed as a base64 string. This is the way LDAP does it. However,
3052         some other software uses a straightforward hex representation. We assume
3053         this if the length is 32. Other lengths fail. */
3054
3055         if (sublen == 24)
3056           {
3057           uschar *coded = b64encode(CUS digest, 16);
3058           DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
3059             "  subject=%s\n  crypted=%s\n", coded, sub[1]+5);
3060           tempcond = (Ustrcmp(coded, sub[1]+5) == 0);
3061           }
3062         else if (sublen == 32)
3063           {
3064           uschar coded[36];
3065           for (int i = 0; i < 16; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3066           coded[32] = 0;
3067           DEBUG(D_auth) debug_printf("crypteq: using MD5+hex hashing\n"
3068             "  subject=%s\n  crypted=%s\n", coded, sub[1]+5);
3069           tempcond = (strcmpic(coded, sub[1]+5) == 0);
3070           }
3071         else
3072           {
3073           DEBUG(D_auth) debug_printf("crypteq: length for MD5 not 24 or 32: "
3074             "fail\n  crypted=%s\n", sub[1]+5);
3075           tempcond = FALSE;
3076           }
3077         }
3078
3079       else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
3080         {
3081         int sublen = Ustrlen(sub[1]+6);
3082         hctx h;
3083         uschar digest[20];
3084
3085         sha1_start(&h);
3086         sha1_end(&h, sub[0], Ustrlen(sub[0]), digest);
3087
3088         /* If the length that we are comparing against is 28, assume the SHA1
3089         digest is expressed as a base64 string. If the length is 40, assume a
3090         straightforward hex representation. Other lengths fail. */
3091
3092         if (sublen == 28)
3093           {
3094           uschar *coded = b64encode(CUS digest, 20);
3095           DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
3096             "  subject=%s\n  crypted=%s\n", coded, sub[1]+6);
3097           tempcond = (Ustrcmp(coded, sub[1]+6) == 0);
3098           }
3099         else if (sublen == 40)
3100           {
3101           uschar coded[44];
3102           for (int i = 0; i < 20; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3103           coded[40] = 0;
3104           DEBUG(D_auth) debug_printf("crypteq: using SHA1+hex hashing\n"
3105             "  subject=%s\n  crypted=%s\n", coded, sub[1]+6);
3106           tempcond = (strcmpic(coded, sub[1]+6) == 0);
3107           }
3108         else
3109           {
3110           DEBUG(D_auth) debug_printf("crypteq: length for SHA-1 not 28 or 40: "
3111             "fail\n  crypted=%s\n", sub[1]+6);
3112           tempcond = FALSE;
3113           }
3114         }
3115
3116       else   /* {crypt} or {crypt16} and non-{ at start */
3117              /* }-for-text-editors */
3118         {
3119         int which = 0;
3120         uschar *coded;
3121
3122         if (strncmpic(sub[1], US"{crypt}", 7) == 0)
3123           {
3124           sub[1] += 7;
3125           which = 1;
3126           }
3127         else if (strncmpic(sub[1], US"{crypt16}", 9) == 0)
3128           {
3129           sub[1] += 9;
3130           which = 2;
3131           }
3132         else if (sub[1][0] == '{')              /* }-for-text-editors */
3133           {
3134           expand_string_message = string_sprintf("unknown encryption mechanism "
3135             "in \"%s\"", sub[1]);
3136           return NULL;
3137           }
3138
3139         switch(which)
3140           {
3141           case 0:  coded = US DEFAULT_CRYPT(CS sub[0], CS sub[1]); break;
3142           case 1:  coded = US crypt(CS sub[0], CS sub[1]); break;
3143           default: coded = US crypt16(CS sub[0], CS sub[1]); break;
3144           }
3145
3146         #define STR(s) # s
3147         #define XSTR(s) STR(s)
3148         DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
3149           "  subject=%s\n  crypted=%s\n",
3150           which == 0 ? XSTR(DEFAULT_CRYPT) : which == 1 ? "crypt" : "crypt16",
3151           coded, sub[1]);
3152         #undef STR
3153         #undef XSTR
3154
3155         /* If the encrypted string contains fewer than two characters (for the
3156         salt), force failure. Otherwise we get false positives: with an empty
3157         string the yield of crypt() is an empty string! */
3158
3159         if (coded)
3160           tempcond = Ustrlen(sub[1]) < 2 ? FALSE : Ustrcmp(coded, sub[1]) == 0;
3161         else if (errno == EINVAL)
3162           tempcond = FALSE;
3163         else
3164           {
3165           expand_string_message = string_sprintf("crypt error: %s\n",
3166             US strerror(errno));
3167           return NULL;
3168           }
3169         }
3170       break;
3171     #endif  /* SUPPORT_CRYPTEQ */
3172
3173     case ECOND_INLIST:
3174     case ECOND_INLISTI:
3175       {
3176       const uschar * list = sub[1];
3177       int sep = 0;
3178       uschar *save_iterate_item = iterate_item;
3179       int (*compare)(const uschar *, const uschar *);
3180
3181       DEBUG(D_expand) debug_printf_indent("condition: %s  item: %s\n", opname, sub[0]);
3182
3183       tempcond = FALSE;
3184       compare = cond_type == ECOND_INLISTI
3185         ? strcmpic : (int (*)(const uschar *, const uschar *)) strcmp;
3186
3187       while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
3188         {
3189         DEBUG(D_expand) debug_printf_indent(" compare %s\n", iterate_item);
3190         if (compare(sub[0], iterate_item) == 0)
3191           {
3192           tempcond = TRUE;
3193           lookup_value = iterate_item;
3194           break;
3195           }
3196         }
3197       iterate_item = save_iterate_item;
3198       }
3199
3200     }   /* Switch for comparison conditions */
3201
3202   *yield = tempcond == testfor;
3203   return s;    /* End of comparison conditions */
3204
3205
3206   /* and/or: computes logical and/or of several conditions */
3207
3208   case ECOND_AND:
3209   case ECOND_OR:
3210   subcondptr = (yield == NULL) ? NULL : &tempcond;
3211   combined_cond = (cond_type == ECOND_AND);
3212
3213   Uskip_whitespace(&s);
3214   if (*s++ != '{') goto COND_FAILED_CURLY_START;        /* }-for-text-editors */
3215
3216   for (;;)
3217     {
3218     /* {-for-text-editors */
3219     if (Uskip_whitespace(&s) == '}') break;
3220     if (*s != '{')                                      /* }-for-text-editors */
3221       {
3222       expand_string_message = string_sprintf("each subcondition "
3223         "inside an \"%s{...}\" condition must be in its own {}", opname);
3224       return NULL;
3225       }
3226
3227     if (!(s = eval_condition(s+1, resetok, subcondptr)))
3228       {
3229       expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
3230         expand_string_message, opname);
3231       return NULL;
3232       }
3233     Uskip_whitespace(&s);
3234
3235     /* {-for-text-editors */
3236     if (*s++ != '}')
3237       {
3238       /* {-for-text-editors */
3239       expand_string_message = string_sprintf("missing } at end of condition "
3240         "inside \"%s\" group", opname);
3241       return NULL;
3242       }
3243
3244     if (yield)
3245       if (cond_type == ECOND_AND)
3246         {
3247         combined_cond &= tempcond;
3248         if (!combined_cond) subcondptr = NULL;  /* once false, don't */
3249         }                                       /* evaluate any more */
3250       else
3251         {
3252         combined_cond |= tempcond;
3253         if (combined_cond) subcondptr = NULL;   /* once true, don't */
3254         }                                       /* evaluate any more */
3255     }
3256
3257   if (yield) *yield = (combined_cond == testfor);
3258   return ++s;
3259
3260
3261   /* forall/forany: iterates a condition with different values */
3262
3263   case ECOND_FORALL:      is_forany = FALSE;  is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3264   case ECOND_FORANY:      is_forany = TRUE;   is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3265   case ECOND_FORALL_JSON: is_forany = FALSE;  is_json = TRUE;  is_jsons = FALSE; goto FORMANY;
3266   case ECOND_FORANY_JSON: is_forany = TRUE;   is_json = TRUE;  is_jsons = FALSE; goto FORMANY;
3267   case ECOND_FORALL_JSONS: is_forany = FALSE; is_json = TRUE;  is_jsons = TRUE;  goto FORMANY;
3268   case ECOND_FORANY_JSONS: is_forany = TRUE;  is_json = TRUE;  is_jsons = TRUE;  goto FORMANY;
3269
3270   FORMANY:
3271     {
3272     const uschar * list;
3273     int sep = 0;
3274     uschar *save_iterate_item = iterate_item;
3275
3276     DEBUG(D_expand) debug_printf_indent("condition: %s\n", opname);
3277
3278     Uskip_whitespace(&s);
3279     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
3280     if (!(sub[0] = expand_string_internal(s,
3281       ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | (yield ? ESI_NOFLAGS : ESI_SKIPPING),
3282       &s, resetok, NULL)))
3283       return NULL;
3284     /* {-for-text-editors */
3285     if (*s++ != '}') goto COND_FAILED_CURLY_END;
3286
3287     Uskip_whitespace(&s);
3288     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
3289
3290     sub[1] = s;
3291
3292     /* Call eval_condition once, with result discarded (as if scanning a
3293     "false" part). This allows us to find the end of the condition, because if
3294     the list it empty, we won't actually evaluate the condition for real. */
3295
3296     if (!(s = eval_condition(sub[1], resetok, NULL)))
3297       {
3298       expand_string_message = string_sprintf("%s inside \"%s\" condition",
3299         expand_string_message, opname);
3300       return NULL;
3301       }
3302     Uskip_whitespace(&s);
3303
3304     /* {-for-text-editors */
3305     if (*s++ != '}')
3306       {
3307       /* {-for-text-editors */
3308       expand_string_message = string_sprintf("missing } at end of condition "
3309         "inside \"%s\"", opname);
3310       return NULL;
3311       }
3312
3313     if (yield) *yield = !testfor;
3314     list = sub[0];
3315     if (is_json) list = dewrap(string_copy(list), US"[]");
3316     while ((iterate_item = is_json
3317       ? json_nextinlist(&list) : string_nextinlist(&list, &sep, NULL, 0)))
3318       {
3319       if (is_jsons)
3320         if (!(iterate_item = dewrap(iterate_item, US"\"\"")))
3321           {
3322           expand_string_message =
3323             string_sprintf("%s wrapping string result for extract jsons",
3324               expand_string_message);
3325           iterate_item = save_iterate_item;
3326           return NULL;
3327           }
3328
3329       DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", opname, iterate_item);
3330       if (!eval_condition(sub[1], resetok, &tempcond))
3331         {
3332         expand_string_message = string_sprintf("%s inside \"%s\" condition",
3333           expand_string_message, opname);
3334         iterate_item = save_iterate_item;
3335         return NULL;
3336         }
3337       DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", opname,
3338         tempcond? "true":"false");
3339
3340       if (yield) *yield = (tempcond == testfor);
3341       if (tempcond == is_forany) break;
3342       }
3343
3344     iterate_item = save_iterate_item;
3345     return s;
3346     }
3347
3348
3349   /* The bool{} expansion condition maps a string to boolean.
3350   The values supported should match those supported by the ACL condition
3351   (acl.c, ACLC_CONDITION) so that we keep to a minimum the different ideas
3352   of true/false.  Note that Router "condition" rules have a different
3353   interpretation, where general data can be used and only a few values
3354   map to FALSE.
3355   Note that readconf.c boolean matching, for boolean configuration options,
3356   only matches true/yes/false/no.
3357   The bool_lax{} condition matches the Router logic, which is much more
3358   liberal. */
3359   case ECOND_BOOL:
3360   case ECOND_BOOL_LAX:
3361     {
3362     uschar *sub_arg[1];
3363     uschar *t, *t2;
3364     uschar *ourname;
3365     size_t len;
3366     BOOL boolvalue = FALSE;
3367
3368     if (Uskip_whitespace(&s) != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
3369     ourname = cond_type == ECOND_BOOL_LAX ? US"bool_lax" : US"bool";
3370     switch(read_subs(sub_arg, 1, 1, &s,
3371             yield ? ESI_NOFLAGS : ESI_SKIPPING, FALSE, ourname, resetok, NULL))
3372       {
3373       case 1: expand_string_message = string_sprintf(
3374                   "too few arguments or bracketing error for %s",
3375                   ourname);
3376       /*FALLTHROUGH*/
3377       case 2:
3378       case 3: return NULL;
3379       }
3380     t = sub_arg[0];
3381     Uskip_whitespace(&t);
3382     if ((len = Ustrlen(t)))
3383       {
3384       /* trailing whitespace: seems like a good idea to ignore it too */
3385       t2 = t + len - 1;
3386       while (isspace(*t2)) t2--;
3387       if (t2 != (t + len))
3388         {
3389         *++t2 = '\0';
3390         len = t2 - t;
3391         }
3392       }
3393     DEBUG(D_expand)
3394       debug_printf_indent("considering %s: %s\n", ourname, len ? t : US"<empty>");
3395     /* logic for the lax case from expand_check_condition(), which also does
3396     expands, and the logic is both short and stable enough that there should
3397     be no maintenance burden from replicating it. */
3398     if (len == 0)
3399       boolvalue = FALSE;
3400     else if (*t == '-'
3401              ? Ustrspn(t+1, "0123456789") == len-1
3402              : Ustrspn(t,   "0123456789") == len)
3403       {
3404       boolvalue = (Uatoi(t) == 0) ? FALSE : TRUE;
3405       /* expand_check_condition only does a literal string "0" check */
3406       if ((cond_type == ECOND_BOOL_LAX) && (len > 1))
3407         boolvalue = TRUE;
3408       }
3409     else if (strcmpic(t, US"true") == 0 || strcmpic(t, US"yes") == 0)
3410       boolvalue = TRUE;
3411     else if (strcmpic(t, US"false") == 0 || strcmpic(t, US"no") == 0)
3412       boolvalue = FALSE;
3413     else if (cond_type == ECOND_BOOL_LAX)
3414       boolvalue = TRUE;
3415     else
3416       {
3417       expand_string_message = string_sprintf("unrecognised boolean "
3418        "value \"%s\"", t);
3419       return NULL;
3420       }
3421     DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", ourname,
3422         boolvalue? "true":"false");
3423     if (yield) *yield = (boolvalue == testfor);
3424     return s;
3425     }
3426
3427 #ifdef SUPPORT_SRS
3428   case ECOND_INBOUND_SRS:
3429     /* ${if inbound_srs {local_part}{secret}  {yes}{no}} */
3430     {
3431     uschar * sub[2];
3432     const pcre2_code * re;
3433     pcre2_match_data * md;
3434     PCRE2_SIZE * ovec;
3435     int quoting = 0;
3436     uschar cksum[4];
3437     BOOL boolvalue = FALSE;
3438
3439     switch(read_subs(sub, 2, 2, CUSS &s,
3440             yield ? ESI_NOFLAGS : ESI_SKIPPING, FALSE, name, resetok, NULL))
3441       {
3442       case 1: expand_string_message = US"too few arguments or bracketing "
3443         "error for inbound_srs";
3444       case 2:
3445       case 3: return NULL;
3446       }
3447
3448     /* Match the given local_part against the SRS-encoded pattern */
3449
3450     re = regex_must_compile(US"^(?i)SRS0=([^=]+)=([A-Z2-7]+)=([^=]*)=(.*)$",
3451                             MCS_CASELESS | MCS_CACHEABLE, FALSE);
3452     md = pcre2_match_data_create(4+1, pcre_gen_ctx);
3453     if (pcre2_match(re, sub[0], PCRE2_ZERO_TERMINATED, 0, PCRE_EOPT,
3454                     md, pcre_gen_mtc_ctx) < 0)
3455       {
3456       DEBUG(D_expand) debug_printf("no match for SRS'd local-part pattern\n");
3457       goto srs_result;
3458       }
3459     ovec = pcre2_get_ovector_pointer(md);
3460
3461     if (sub[0][0] == '"')
3462       quoting = 1;
3463     else for (uschar * s = sub[0]; *s; s++)
3464       if (!isalnum(*s) && Ustrchr(".!#$%&'*+-/=?^_`{|}~", *s) == NULL)
3465         { quoting = 1; break; }
3466     if (quoting)
3467       DEBUG(D_expand) debug_printf_indent("auto-quoting local part\n");
3468
3469     /* Record the (quoted, if needed) decoded recipient as $srs_recipient */
3470
3471     srs_recipient = string_sprintf("%.*s%.*S%.*s@%.*S",         /* lowercased */
3472                       quoting, "\"",
3473                       (int) (ovec[9]-ovec[8]), sub[0] + ovec[8],  /* substr 4 */
3474                       quoting, "\"",
3475                       (int) (ovec[7]-ovec[6]), sub[0] + ovec[6]); /* substr 3 */
3476
3477     /* If a zero-length secret was given, we're done.  Otherwise carry on
3478     and validate the given SRS local_part againt our secret. */
3479
3480     if (!*sub[1])
3481       {
3482       boolvalue = TRUE;
3483       goto srs_result;
3484       }
3485
3486     /* check the timestamp */
3487       {
3488       struct timeval now;
3489       uschar * ss = sub[0] + ovec[4];   /* substring 2, the timestamp */
3490       long d;
3491       int n;
3492
3493       gettimeofday(&now, NULL);
3494       now.tv_sec /= 86400;              /* days since epoch */
3495
3496       /* Decode substring 2 from base32 to a number */
3497
3498       for (d = 0, n = ovec[5]-ovec[4]; n; n--)
3499         {
3500         uschar * t = Ustrchr(base32_chars, *ss++);
3501         d = d * 32 + (t - base32_chars);
3502         }
3503
3504       if (((now.tv_sec - d) & 0x3ff) > 10)      /* days since SRS generated */
3505         {
3506         DEBUG(D_expand) debug_printf("SRS too old\n");
3507         goto srs_result;
3508         }
3509       }
3510
3511     /* check length of substring 1, the offered checksum */
3512
3513     if (ovec[3]-ovec[2] != 4)
3514       {
3515       DEBUG(D_expand) debug_printf("SRS checksum wrong size\n");
3516       goto srs_result;
3517       }
3518
3519     /* Hash the address with our secret, and compare that computed checksum
3520     with the one extracted from the arg */
3521
3522     hmac_md5(sub[1], srs_recipient, cksum, sizeof(cksum));
3523     if (Ustrncmp(cksum, sub[0] + ovec[2], 4) != 0)
3524       {
3525       DEBUG(D_expand) debug_printf("SRS checksum mismatch\n");
3526       goto srs_result;
3527       }
3528     boolvalue = TRUE;
3529
3530 srs_result:
3531     /* pcre2_match_data_free(md);       gen ctx needs no free */
3532     if (yield) *yield = (boolvalue == testfor);
3533     return s;
3534     }
3535 #endif /*SUPPORT_SRS*/
3536
3537   /* Unknown condition */
3538
3539   default:
3540     if (!expand_string_message || !*expand_string_message)
3541       expand_string_message = string_sprintf("unknown condition \"%s\"", opname);
3542     return NULL;
3543   }   /* End switch on condition type */
3544
3545 /* Missing braces at start and end of data */
3546
3547 COND_FAILED_CURLY_START:
3548 expand_string_message = string_sprintf("missing { after \"%s\"", opname);
3549 return NULL;
3550
3551 COND_FAILED_CURLY_END:
3552 expand_string_message = string_sprintf("missing } at end of \"%s\" condition",
3553   opname);
3554 return NULL;
3555
3556 /* A condition requires code that is not compiled */
3557
3558 #if !defined(SUPPORT_PAM) || !defined(RADIUS_CONFIG_FILE) || \
3559     !defined(LOOKUP_LDAP) || !defined(CYRUS_PWCHECK_SOCKET) || \
3560     !defined(SUPPORT_CRYPTEQ) || !defined(CYRUS_SASLAUTHD_SOCKET)
3561 COND_FAILED_NOT_COMPILED:
3562 expand_string_message = string_sprintf("support for \"%s\" not compiled",
3563   opname);
3564 return NULL;
3565 #endif
3566 }
3567
3568
3569
3570
3571 /*************************************************
3572 *          Save numerical variables              *
3573 *************************************************/
3574
3575 /* This function is called from items such as "if" that want to preserve and
3576 restore the numbered variables.
3577
3578 Arguments:
3579   save_expand_string    points to an array of pointers to set
3580   save_expand_nlength   points to an array of ints for the lengths
3581
3582 Returns:                the value of expand max to save
3583 */
3584
3585 static int
3586 save_expand_strings(const uschar **save_expand_nstring, int *save_expand_nlength)
3587 {
3588 for (int i = 0; i <= expand_nmax; i++)
3589   {
3590   save_expand_nstring[i] = expand_nstring[i];
3591   save_expand_nlength[i] = expand_nlength[i];
3592   }
3593 return expand_nmax;
3594 }
3595
3596
3597
3598 /*************************************************
3599 *           Restore numerical variables          *
3600 *************************************************/
3601
3602 /* This function restored saved values of numerical strings.
3603
3604 Arguments:
3605   save_expand_nmax      the number of strings to restore
3606   save_expand_string    points to an array of pointers
3607   save_expand_nlength   points to an array of ints
3608
3609 Returns:                nothing
3610 */
3611
3612 static void
3613 restore_expand_strings(int save_expand_nmax, const uschar **save_expand_nstring,
3614   int *save_expand_nlength)
3615 {
3616 expand_nmax = save_expand_nmax;
3617 for (int i = 0; i <= expand_nmax; i++)
3618   {
3619   expand_nstring[i] = save_expand_nstring[i];
3620   expand_nlength[i] = save_expand_nlength[i];
3621   }
3622 }
3623
3624
3625
3626
3627
3628 /*************************************************
3629 *            Handle yes/no substrings            *
3630 *************************************************/
3631
3632 /* This function is used by ${if}, ${lookup} and ${extract} to handle the
3633 alternative substrings that depend on whether or not the condition was true,
3634 or the lookup or extraction succeeded. The substrings always have to be
3635 expanded, to check their syntax, but "skipping" is set when the result is not
3636 needed - this avoids unnecessary nested lookups.
3637
3638 Arguments:
3639   flags
3640    skipping       TRUE if we were skipping when this item was reached
3641   yes            TRUE if the first string is to be used, else use the second
3642   save_lookup    a value to put back into lookup_value before the 2nd expansion
3643   sptr           points to the input string pointer
3644   yieldptr       points to the output growable-string pointer
3645   type           "lookup", "if", "extract", "run", "env", "listextract" or
3646                  "certextract" for error message
3647   resetok        if not NULL, pointer to flag - write FALSE if unsafe to reset
3648                 the store.
3649
3650 Returns:         0 OK; lookup_value has been reset to save_lookup
3651                  1 expansion failed
3652                  2 expansion failed because of bracketing error
3653 */
3654
3655 static int
3656 process_yesno(esi_flags flags, BOOL yes, uschar *save_lookup, const uschar **sptr,
3657   gstring ** yieldptr, uschar *type, BOOL *resetok)
3658 {
3659 int rc = 0;
3660 const uschar *s = *sptr;    /* Local value */
3661 uschar *sub1, *sub2;
3662 const uschar * errwhere;
3663
3664 flags &= ESI_SKIPPING;          /* Ignore all buf the skipping flag */
3665
3666 /* If there are no following strings, we substitute the contents of $value for
3667 lookups and for extractions in the success case. For the ${if item, the string
3668 "true" is substituted. In the fail case, nothing is substituted for all three
3669 items. */
3670
3671 if (skip_whitespace(&s) == '}')
3672   {
3673   if (type[0] == 'i')
3674     {
3675     if (yes && !(flags & ESI_SKIPPING))
3676       *yieldptr = string_catn(*yieldptr, US"true", 4);
3677     }
3678   else
3679     {
3680     if (yes && lookup_value && !(flags & ESI_SKIPPING))
3681       *yieldptr = string_cat(*yieldptr, lookup_value);
3682     lookup_value = save_lookup;
3683     }
3684   s++;
3685   goto RETURN;
3686   }
3687
3688 /* The first following string must be braced. */
3689
3690 if (*s++ != '{')
3691   {
3692   errwhere = US"'yes' part did not start with '{'";             /*}}*/
3693   goto FAILED_CURLY;
3694   }
3695
3696 /* Expand the first substring. Forced failures are noticed only if we actually
3697 want this string. Set skipping in the call in the fail case (this will always
3698 be the case if we were already skipping). */
3699
3700 sub1 = expand_string_internal(s,
3701   ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | (yes ? ESI_NOFLAGS : ESI_SKIPPING),
3702   &s, resetok, NULL);
3703 if (sub1 == NULL && (yes || !f.expand_string_forcedfail)) goto FAILED;
3704 f.expand_string_forcedfail = FALSE;
3705                                                                 /*{{*/
3706 if (*s++ != '}')
3707   {
3708   errwhere = US"'yes' part did not end with '}'";
3709   goto FAILED_CURLY;
3710   }
3711
3712 /* If we want the first string, add it to the output */
3713
3714 if (yes)
3715   *yieldptr = string_cat(*yieldptr, sub1);
3716
3717 /* If this is called from a lookup/env or a (cert)extract, we want to restore
3718 $value to what it was at the start of the item, so that it has this value
3719 during the second string expansion. For the call from "if" or "run" to this
3720 function, save_lookup is set to lookup_value, so that this statement does
3721 nothing. */
3722
3723 lookup_value = save_lookup;
3724
3725 /* There now follows either another substring, or "fail", or nothing. This
3726 time, forced failures are noticed only if we want the second string. We must
3727 set skipping in the nested call if we don't want this string, or if we were
3728 already skipping. */
3729
3730 if (skip_whitespace(&s) == '{')                                 /*}*/
3731   {
3732   esi_flags s_flags = ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags;
3733   if (yes) s_flags |= ESI_SKIPPING;
3734   sub2 = expand_string_internal(s+1, s_flags, &s, resetok, NULL);
3735   if (!sub2 && (!yes || !f.expand_string_forcedfail)) goto FAILED;
3736   f.expand_string_forcedfail = FALSE;                           /*{*/
3737   if (*s++ != '}')
3738     {
3739     errwhere = US"'no' part did not start with '{'";            /*}*/
3740     goto FAILED_CURLY;
3741     }
3742
3743   /* If we want the second string, add it to the output */
3744
3745   if (!yes)
3746     *yieldptr = string_cat(*yieldptr, sub2);
3747   }
3748                                                                 /*{{*/
3749 /* If there is no second string, but the word "fail" is present when the use of
3750 the second string is wanted, set a flag indicating it was a forced failure
3751 rather than a syntactic error. Swallow the terminating } in case this is nested
3752 inside another lookup or if or extract. */
3753
3754 else if (*s != '}')
3755   {
3756   uschar name[256];
3757   /* deconst cast ok here as source is s anyway */
3758   s = US read_name(name, sizeof(name), s, US"_");
3759   if (Ustrcmp(name, "fail") == 0)
3760     {
3761     if (!yes && !(flags & ESI_SKIPPING))
3762       {
3763       Uskip_whitespace(&s);                                     /*{{*/
3764       if (*s++ != '}')
3765         {
3766         errwhere = US"did not close with '}' after forcedfail";
3767         goto FAILED_CURLY;
3768         }
3769       expand_string_message =
3770         string_sprintf("\"%s\" failed and \"fail\" requested", type);
3771       f.expand_string_forcedfail = TRUE;
3772       goto FAILED;
3773       }
3774     }
3775   else
3776     {
3777     expand_string_message =
3778       string_sprintf("syntax error in \"%s\" item - \"fail\" expected", type);
3779     goto FAILED;
3780     }
3781   }
3782
3783 /* All we have to do now is to check on the final closing brace. */
3784
3785 skip_whitespace(&s);                                            /*{{*/
3786 if (*s++ != '}')
3787   {
3788   errwhere = US"did not close with '}'";
3789   goto FAILED_CURLY;
3790   }
3791
3792
3793 RETURN:
3794 /* Update the input pointer value before returning */
3795 *sptr = s;
3796 return rc;
3797
3798 FAILED_CURLY:
3799   /* Get here if there is a bracketing failure */
3800   expand_string_message = string_sprintf(
3801     "curly-bracket problem in conditional yes/no parsing: %s\n"
3802     " remaining string is '%s'", errwhere, --s);
3803   rc = 2;
3804   goto RETURN;
3805
3806 FAILED:
3807   /* Get here for other failures */
3808   rc = 1;
3809   goto RETURN;
3810 }
3811
3812
3813
3814
3815 /********************************************************
3816 * prvs: Get last three digits of days since Jan 1, 1970 *
3817 ********************************************************/
3818
3819 /* This is needed to implement the "prvs" BATV reverse
3820    path signing scheme
3821
3822 Argument: integer "days" offset to add or substract to
3823           or from the current number of days.
3824
3825 Returns:  pointer to string containing the last three
3826           digits of the number of days since Jan 1, 1970,
3827           modified by the offset argument, NULL if there
3828           was an error in the conversion.
3829
3830 */
3831
3832 static uschar *
3833 prvs_daystamp(int day_offset)
3834 {
3835 uschar * days = store_get(32, GET_UNTAINTED);      /* Need at least 24 for cases */
3836 (void)string_format(days, 32, TIME_T_FMT,          /* where TIME_T_FMT is %lld */
3837   (time(NULL) + day_offset*86400)/86400);
3838 return (Ustrlen(days) >= 3) ? &days[Ustrlen(days)-3] : US"100";
3839 }
3840
3841
3842
3843 /********************************************************
3844 *   prvs: perform HMAC-SHA1 computation of prvs bits    *
3845 ********************************************************/
3846
3847 /* This is needed to implement the "prvs" BATV reverse
3848    path signing scheme
3849
3850 Arguments:
3851   address RFC2821 Address to use
3852       key The key to use (must be less than 64 characters
3853           in size)
3854   key_num Single-digit key number to use. Defaults to
3855           '0' when NULL.
3856
3857 Returns:  pointer to string containing the first three
3858           bytes of the final hash in hex format, NULL if
3859           there was an error in the process.
3860 */
3861
3862 static uschar *
3863 prvs_hmac_sha1(uschar *address, uschar *key, uschar *key_num, uschar *daystamp)
3864 {
3865 gstring * hash_source;
3866 uschar * p;
3867 hctx h;
3868 uschar innerhash[20];
3869 uschar finalhash[20];
3870 uschar innerkey[64];
3871 uschar outerkey[64];
3872 uschar *finalhash_hex;
3873
3874 if (!key_num)
3875   key_num = US"0";
3876
3877 if (Ustrlen(key) > 64)
3878   return NULL;
3879
3880 hash_source = string_catn(NULL, key_num, 1);
3881 hash_source = string_catn(hash_source, daystamp, 3);
3882 hash_source = string_cat(hash_source, address);
3883 (void) string_from_gstring(hash_source);
3884
3885 DEBUG(D_expand)
3886   debug_printf_indent("prvs: hash source is '%s'\n", hash_source->s);
3887
3888 memset(innerkey, 0x36, 64);
3889 memset(outerkey, 0x5c, 64);
3890
3891 for (int i = 0; i < Ustrlen(key); i++)
3892   {
3893   innerkey[i] ^= key[i];
3894   outerkey[i] ^= key[i];
3895   }
3896
3897 chash_start(HMAC_SHA1, &h);
3898 chash_mid(HMAC_SHA1, &h, innerkey);
3899 chash_end(HMAC_SHA1, &h, hash_source->s, hash_source->ptr, innerhash);
3900
3901 chash_start(HMAC_SHA1, &h);
3902 chash_mid(HMAC_SHA1, &h, outerkey);
3903 chash_end(HMAC_SHA1, &h, innerhash, 20, finalhash);
3904
3905 /* Hashing is deemed sufficient to de-taint any input data */
3906
3907 p = finalhash_hex = store_get(40, GET_UNTAINTED);
3908 for (int i = 0; i < 3; i++)
3909   {
3910   *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
3911   *p++ = hex_digits[finalhash[i] & 0x0f];
3912   }
3913 *p = '\0';
3914
3915 return finalhash_hex;
3916 }
3917
3918
3919
3920
3921 /*************************************************
3922 *        Join a file onto the output string      *
3923 *************************************************/
3924
3925 /* This is used for readfile/readsock and after a run expansion.
3926 It joins the contents of a file onto the output string, globally replacing
3927 newlines with a given string (optionally).
3928
3929 Arguments:
3930   f            the FILE
3931   yield        pointer to the expandable string struct
3932   eol          newline replacement string, or NULL
3933
3934 Returns:       new pointer for expandable string, terminated if non-null
3935 */
3936
3937 gstring *
3938 cat_file(FILE * f, gstring * yield, uschar * eol)
3939 {
3940 uschar buffer[1024];
3941
3942 while (Ufgets(buffer, sizeof(buffer), f))
3943   {
3944   int len = Ustrlen(buffer);
3945   if (eol && buffer[len-1] == '\n') len--;
3946   yield = string_catn(yield, buffer, len);
3947   if (eol && buffer[len])
3948     yield = string_cat(yield, eol);
3949   }
3950 return yield;
3951 }
3952
3953
3954 #ifndef DISABLE_TLS
3955 gstring *
3956 cat_file_tls(void * tls_ctx, gstring * yield, uschar * eol)
3957 {
3958 int rc;
3959 uschar buffer[1024];
3960
3961 /*XXX could we read direct into a pre-grown string? */
3962
3963 while ((rc = tls_read(tls_ctx, buffer, sizeof(buffer))) > 0)
3964   for (uschar * s = buffer; rc--; s++)
3965     yield = eol && *s == '\n'
3966       ? string_cat(yield, eol) : string_catn(yield, s, 1);
3967
3968 /* We assume that all errors, and any returns of zero bytes,
3969 are actually EOF. */
3970
3971 return yield;
3972 }
3973 #endif
3974
3975
3976 /*************************************************
3977 *          Evaluate numeric expression           *
3978 *************************************************/
3979
3980 /* This is a set of mutually recursive functions that evaluate an arithmetic
3981 expression involving + - * / % & | ^ ~ << >> and parentheses. The only one of
3982 these functions that is called from elsewhere is eval_expr, whose interface is:
3983
3984 Arguments:
3985   sptr        pointer to the pointer to the string - gets updated
3986   decimal     TRUE if numbers are to be assumed decimal
3987   error       pointer to where to put an error message - must be NULL on input
3988   endket      TRUE if ')' must terminate - FALSE for external call
3989
3990 Returns:      on success: the value of the expression, with *error still NULL
3991               on failure: an undefined value, with *error = a message
3992 */
3993
3994 static int_eximarith_t eval_op_or(uschar **, BOOL, uschar **);
3995
3996
3997 static int_eximarith_t
3998 eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket)
3999 {
4000 uschar *s = *sptr;
4001 int_eximarith_t x = eval_op_or(&s, decimal, error);
4002
4003 if (!*error)
4004   if (endket)
4005     if (*s != ')')
4006       *error = US"expecting closing parenthesis";
4007     else
4008       while (isspace(*++s));
4009   else if (*s)
4010     *error = US"expecting operator";
4011 *sptr = s;
4012 return x;
4013 }
4014
4015
4016 static int_eximarith_t
4017 eval_number(uschar **sptr, BOOL decimal, uschar **error)
4018 {
4019 int c;
4020 int_eximarith_t n;
4021 uschar *s = *sptr;
4022
4023 if (isdigit((c = Uskip_whitespace(&s))))
4024   {
4025   int count;
4026   (void)sscanf(CS s, (decimal? SC_EXIM_DEC "%n" : SC_EXIM_ARITH "%n"), &n, &count);
4027   s += count;
4028   switch (tolower(*s))
4029     {
4030     default: break;
4031     case 'k': n *= 1024; s++; break;
4032     case 'm': n *= 1024*1024; s++; break;
4033     case 'g': n *= 1024*1024*1024; s++; break;
4034     }
4035   Uskip_whitespace(&s);
4036   }
4037 else if (c == '(')
4038   {
4039   s++;
4040   n = eval_expr(&s, decimal, error, 1);
4041   }
4042 else
4043   {
4044   *error = US"expecting number or opening parenthesis";
4045   n = 0;
4046   }
4047 *sptr = s;
4048 return n;
4049 }
4050
4051
4052 static int_eximarith_t
4053 eval_op_unary(uschar **sptr, BOOL decimal, uschar **error)
4054 {
4055 uschar *s = *sptr;
4056 int_eximarith_t x;
4057 Uskip_whitespace(&s);
4058 if (*s == '+' || *s == '-' || *s == '~')
4059   {
4060   int op = *s++;
4061   x = eval_op_unary(&s, decimal, error);
4062   if (op == '-') x = -x;
4063     else if (op == '~') x = ~x;
4064   }
4065 else
4066   x = eval_number(&s, decimal, error);
4067
4068 *sptr = s;
4069 return x;
4070 }
4071
4072
4073 static int_eximarith_t
4074 eval_op_mult(uschar **sptr, BOOL decimal, uschar **error)
4075 {
4076 uschar *s = *sptr;
4077 int_eximarith_t x = eval_op_unary(&s, decimal, error);
4078 if (!*error)
4079   {
4080   while (*s == '*' || *s == '/' || *s == '%')
4081     {
4082     int op = *s++;
4083     int_eximarith_t y = eval_op_unary(&s, decimal, error);
4084     if (*error) break;
4085     /* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give
4086      * a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which
4087      * is a bug somewhere in [gcc 4.2.1, FreeBSD, amd64].  In fact, -N*-M where
4088      * -N*M is INT_MIN will yield INT_MIN.
4089      * Since we don't support floating point, this is somewhat simpler.
4090      * Ideally, we'd return an error, but since we overflow for all other
4091      * arithmetic, consistency suggests otherwise, but what's the correct value
4092      * to use?  There is none.
4093      * The C standard guarantees overflow for unsigned arithmetic but signed
4094      * overflow invokes undefined behaviour; in practice, this is overflow
4095      * except for converting INT_MIN to INT_MAX+1.  We also can't guarantee
4096      * that long/longlong larger than int are available, or we could just work
4097      * with larger types.  We should consider whether to guarantee 32bit eval
4098      * and 64-bit working variables, with errors returned.  For now ...
4099      * So, the only SIGFPEs occur with a non-shrinking div/mod, thus -1; we
4100      * can just let the other invalid results occur otherwise, as they have
4101      * until now.  For this one case, we can coerce.
4102      */
4103     if (y == -1 && x == EXIM_ARITH_MIN && op != '*')
4104       {
4105       DEBUG(D_expand)
4106         debug_printf("Integer exception dodging: " PR_EXIM_ARITH "%c-1 coerced to " PR_EXIM_ARITH "\n",
4107             EXIM_ARITH_MIN, op, EXIM_ARITH_MAX);
4108       x = EXIM_ARITH_MAX;
4109       continue;
4110       }
4111     if (op == '*')
4112       x *= y;
4113     else
4114       {
4115       if (y == 0)
4116         {
4117         *error = (op == '/') ? US"divide by zero" : US"modulo by zero";
4118         x = 0;
4119         break;
4120         }
4121       if (op == '/')
4122         x /= y;
4123       else
4124         x %= y;
4125       }
4126     }
4127   }
4128 *sptr = s;
4129 return x;
4130 }
4131
4132
4133 static int_eximarith_t
4134 eval_op_sum(uschar **sptr, BOOL decimal, uschar **error)
4135 {
4136 uschar *s = *sptr;
4137 int_eximarith_t x = eval_op_mult(&s, decimal, error);
4138 if (!*error)
4139   {
4140   while (*s == '+' || *s == '-')
4141     {
4142     int op = *s++;
4143     int_eximarith_t y = eval_op_mult(&s, decimal, error);
4144     if (*error) break;
4145     if (  (x >=   EXIM_ARITH_MAX/2  && x >=   EXIM_ARITH_MAX/2)
4146        || (x <= -(EXIM_ARITH_MAX/2) && y <= -(EXIM_ARITH_MAX/2)))
4147       {                 /* over-conservative check */
4148       *error = op == '+'
4149         ? US"overflow in sum" : US"overflow in difference";
4150       break;
4151       }
4152     if (op == '+') x += y; else x -= y;
4153     }
4154   }
4155 *sptr = s;
4156 return x;
4157 }
4158
4159
4160 static int_eximarith_t
4161 eval_op_shift(uschar **sptr, BOOL decimal, uschar **error)
4162 {
4163 uschar *s = *sptr;
4164 int_eximarith_t x = eval_op_sum(&s, decimal, error);
4165 if (!*error)
4166   {
4167   while ((*s == '<' || *s == '>') && s[1] == s[0])
4168     {
4169     int_eximarith_t y;
4170     int op = *s++;
4171     s++;
4172     y = eval_op_sum(&s, decimal, error);
4173     if (*error) break;
4174     if (op == '<') x <<= y; else x >>= y;
4175     }
4176   }
4177 *sptr = s;
4178 return x;
4179 }
4180
4181
4182 static int_eximarith_t
4183 eval_op_and(uschar **sptr, BOOL decimal, uschar **error)
4184 {
4185 uschar *s = *sptr;
4186 int_eximarith_t x = eval_op_shift(&s, decimal, error);
4187 if (!*error)
4188   {
4189   while (*s == '&')
4190     {
4191     int_eximarith_t y;
4192     s++;
4193     y = eval_op_shift(&s, decimal, error);
4194     if (*error) break;
4195     x &= y;
4196     }
4197   }
4198 *sptr = s;
4199 return x;
4200 }
4201
4202
4203 static int_eximarith_t
4204 eval_op_xor(uschar **sptr, BOOL decimal, uschar **error)
4205 {
4206 uschar *s = *sptr;
4207 int_eximarith_t x = eval_op_and(&s, decimal, error);
4208 if (!*error)
4209   {
4210   while (*s == '^')
4211     {
4212     int_eximarith_t y;
4213     s++;
4214     y = eval_op_and(&s, decimal, error);
4215     if (*error) break;
4216     x ^= y;
4217     }
4218   }
4219 *sptr = s;
4220 return x;
4221 }
4222
4223
4224 static int_eximarith_t
4225 eval_op_or(uschar **sptr, BOOL decimal, uschar **error)
4226 {
4227 uschar *s = *sptr;
4228 int_eximarith_t x = eval_op_xor(&s, decimal, error);
4229 if (!*error)
4230   {
4231   while (*s == '|')
4232     {
4233     int_eximarith_t y;
4234     s++;
4235     y = eval_op_xor(&s, decimal, error);
4236     if (*error) break;
4237     x |= y;
4238     }
4239   }
4240 *sptr = s;
4241 return x;
4242 }
4243
4244
4245
4246 /************************************************/
4247 /* Comparison operation for sort expansion.  We need to avoid
4248 re-expanding the fields being compared, so need a custom routine.
4249
4250 Arguments:
4251  cond_type              Comparison operator code
4252  leftarg, rightarg      Arguments for comparison
4253
4254 Return true iff (leftarg compare rightarg)
4255 */
4256
4257 static BOOL
4258 sortsbefore(int cond_type, BOOL alpha_cond,
4259   const uschar * leftarg, const uschar * rightarg)
4260 {
4261 int_eximarith_t l_num, r_num;
4262
4263 if (!alpha_cond)
4264   {
4265   l_num = expanded_string_integer(leftarg, FALSE);
4266   if (expand_string_message) return FALSE;
4267   r_num = expanded_string_integer(rightarg, FALSE);
4268   if (expand_string_message) return FALSE;
4269
4270   switch (cond_type)
4271     {
4272     case ECOND_NUM_G:   return l_num >  r_num;
4273     case ECOND_NUM_GE:  return l_num >= r_num;
4274     case ECOND_NUM_L:   return l_num <  r_num;
4275     case ECOND_NUM_LE:  return l_num <= r_num;
4276     default: break;
4277     }
4278   }
4279 else
4280   switch (cond_type)
4281     {
4282     case ECOND_STR_LT:  return Ustrcmp (leftarg, rightarg) <  0;
4283     case ECOND_STR_LTI: return strcmpic(leftarg, rightarg) <  0;
4284     case ECOND_STR_LE:  return Ustrcmp (leftarg, rightarg) <= 0;
4285     case ECOND_STR_LEI: return strcmpic(leftarg, rightarg) <= 0;
4286     case ECOND_STR_GT:  return Ustrcmp (leftarg, rightarg) >  0;
4287     case ECOND_STR_GTI: return strcmpic(leftarg, rightarg) >  0;
4288     case ECOND_STR_GE:  return Ustrcmp (leftarg, rightarg) >= 0;
4289     case ECOND_STR_GEI: return strcmpic(leftarg, rightarg) >= 0;
4290     default: break;
4291     }
4292 return FALSE;   /* should not happen */
4293 }
4294
4295
4296 /* Expand a named list.  Return false on failure. */
4297 static gstring *
4298 expand_listnamed(gstring * yield, const uschar * name, const uschar * listtype)
4299 {
4300 tree_node *t = NULL;
4301 const uschar * list;
4302 int sep = 0;
4303 uschar * item;
4304 BOOL needsep = FALSE;
4305 #define LISTNAMED_BUF_SIZE 256
4306 uschar b[LISTNAMED_BUF_SIZE];
4307 uschar * buffer = b;
4308
4309 if (*name == '+') name++;
4310 if (!listtype)          /* no-argument version */
4311   {
4312   if (  !(t = tree_search(addresslist_anchor, name))
4313      && !(t = tree_search(domainlist_anchor,  name))
4314      && !(t = tree_search(hostlist_anchor,    name)))
4315     t = tree_search(localpartlist_anchor, name);
4316   }
4317 else switch(*listtype)  /* specific list-type version */
4318   {
4319   case 'a': t = tree_search(addresslist_anchor,   name); break;
4320   case 'd': t = tree_search(domainlist_anchor,    name); break;
4321   case 'h': t = tree_search(hostlist_anchor,      name); break;
4322   case 'l': t = tree_search(localpartlist_anchor, name); break;
4323   default:
4324     expand_string_message = US"bad suffix on \"list\" operator";
4325     return yield;
4326   }
4327
4328 if(!t)
4329   {
4330   expand_string_message = string_sprintf("\"%s\" is not a %snamed list",
4331     name, !listtype?""
4332       : *listtype=='a'?"address "
4333       : *listtype=='d'?"domain "
4334       : *listtype=='h'?"host "
4335       : *listtype=='l'?"localpart "
4336       : 0);
4337   return yield;
4338   }
4339
4340 list = ((namedlist_block *)(t->data.ptr))->string;
4341
4342 /* The list could be quite long so we (re)use a buffer for each element
4343 rather than getting each in new memory */
4344
4345 if (is_tainted(list)) buffer = store_get(LISTNAMED_BUF_SIZE, GET_TAINTED);
4346 while ((item = string_nextinlist(&list, &sep, buffer, LISTNAMED_BUF_SIZE)))
4347   {
4348   uschar * buf = US" : ";
4349   if (needsep)
4350     yield = string_catn(yield, buf, 3);
4351   else
4352     needsep = TRUE;
4353
4354   if (*item == '+')     /* list item is itself a named list */
4355     {
4356     yield = expand_listnamed(yield, item, listtype);
4357     if (expand_string_message)
4358       return yield;
4359     }
4360
4361   else if (sep != ':')  /* item from non-colon-sep list, re-quote for colon list-separator */
4362     {
4363     char tok[3];
4364     tok[0] = sep; tok[1] = ':'; tok[2] = 0;
4365
4366     for(char * cp; cp = strpbrk(CCS item, tok); item = US cp)
4367       {
4368       yield = string_catn(yield, item, cp - CS item);
4369       if (*cp++ == ':') /* colon in a non-colon-sep list item, needs doubling */
4370         yield = string_catn(yield, US"::", 2);
4371       else              /* sep in item; should already be doubled; emit once */
4372         {
4373         yield = string_catn(yield, US tok, 1);
4374         if (*cp == sep) cp++;
4375         }
4376       }
4377     yield = string_cat(yield, item);
4378     }
4379   else
4380     yield = string_cat(yield, item);
4381   }
4382 return yield;
4383 }
4384
4385
4386
4387 /************************************************/
4388 static void
4389 debug_expansion_interim(const uschar * what, const uschar * value, int nchar,
4390   BOOL skipping)
4391 {
4392 DEBUG(D_noutf8)
4393   debug_printf_indent("|");
4394 else
4395   debug_printf_indent(UTF8_VERT_RIGHT);
4396
4397 for (int fill = 11 - Ustrlen(what); fill > 0; fill--)
4398   DEBUG(D_noutf8)
4399     debug_printf("-");
4400   else
4401     debug_printf(UTF8_HORIZ);
4402
4403 debug_printf("%s: %.*s\n", what, nchar, value);
4404 if (is_tainted(value))
4405   {
4406   DEBUG(D_noutf8)
4407     debug_printf_indent("%s     \\__", skipping ? "|     " : "      ");
4408   else
4409     debug_printf_indent("%s",
4410       skipping
4411       ? UTF8_VERT "             " : "           " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ);
4412   debug_printf("(tainted)\n");
4413   }
4414 }
4415
4416
4417 /*************************************************
4418 *                 Expand string                  *
4419 *************************************************/
4420
4421 /* Returns either an unchanged string, or the expanded string in stacking pool
4422 store. Interpreted sequences are:
4423
4424    \...                    normal escaping rules
4425    $name                   substitutes the variable
4426    ${name}                 ditto
4427    ${op:string}            operates on the expanded string value
4428    ${item{arg1}{arg2}...}  expands the args and then does the business
4429                              some literal args are not enclosed in {}
4430
4431 There are now far too many operators and item types to make it worth listing
4432 them here in detail any more.
4433
4434 We use an internal routine recursively to handle embedded substrings. The
4435 external function follows. The yield is NULL if the expansion failed, and there
4436 are two cases: if something collapsed syntactically, or if "fail" was given
4437 as the action on a lookup failure. These can be distinguished by looking at the
4438 variable expand_string_forcedfail, which is TRUE in the latter case.
4439
4440 The skipping flag is set true when expanding a substring that isn't actually
4441 going to be used (after "if" or "lookup") and it prevents lookups from
4442 happening lower down.
4443
4444 Store usage: At start, a store block of the length of the input plus 64
4445 is obtained. This is expanded as necessary by string_cat(), which might have to
4446 get a new block, or might be able to expand the original. At the end of the
4447 function we can release any store above that portion of the yield block that
4448 was actually used. In many cases this will be optimal.
4449
4450 However: if the first item in the expansion is a variable name or header name,
4451 we reset the store before processing it; if the result is in fresh store, we
4452 use that without copying. This is helpful for expanding strings like
4453 $message_headers which can get very long.
4454
4455 There's a problem if a ${dlfunc item has side-effects that cause allocation,
4456 since resetting the store at the end of the expansion will free store that was
4457 allocated by the plugin code as well as the slop after the expanded string. So
4458 we skip any resets if ${dlfunc } has been used. The same applies for ${acl }
4459 and, given the acl condition, ${if }. This is an unfortunate consequence of
4460 string expansion becoming too powerful.
4461
4462 Arguments:
4463   string         the string to be expanded
4464   flags
4465    brace_ends     expansion is to stop at }
4466    honour_dollar  TRUE if $ is to be expanded,
4467                   FALSE if it's just another character
4468    skipping       TRUE for recursive calls when the value isn't actually going
4469                   to be used (to allow for optimisation)
4470   left           if not NULL, a pointer to the first character after the
4471                  expansion is placed here (typically used with brace_ends)
4472   resetok_p      if not NULL, pointer to flag - write FALSE if unsafe to reset
4473                  the store.
4474   textonly_p     if not NULL, pointer to flag - write bool for only-met-text
4475
4476 Returns:         NULL if expansion fails:
4477                    expand_string_forcedfail is set TRUE if failure was forced
4478                    expand_string_message contains a textual error message
4479                  a pointer to the expanded string on success
4480 */
4481
4482 static uschar *
4483 expand_string_internal(const uschar * string, esi_flags flags, const uschar ** left,
4484   BOOL *resetok_p, BOOL * textonly_p)
4485 {
4486 rmark reset_point = store_mark();
4487 gstring * yield = string_get(Ustrlen(string) + 64);
4488 int item_type;
4489 const uschar * s = string;
4490 const uschar * save_expand_nstring[EXPAND_MAXN+1];
4491 int save_expand_nlength[EXPAND_MAXN+1];
4492 BOOL resetok = TRUE, first = TRUE, textonly = TRUE;
4493
4494 expand_level++;
4495 f.expand_string_forcedfail = FALSE;
4496 expand_string_message = US"";
4497
4498 if (is_tainted(string))
4499   {
4500   expand_string_message =
4501     string_sprintf("attempt to expand tainted string '%s'", s);
4502   log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
4503   goto EXPAND_FAILED;
4504   }
4505
4506 while (*s)
4507   {
4508   uschar name[256];
4509
4510   DEBUG(D_expand)
4511     {
4512     DEBUG(D_noutf8)
4513       debug_printf_indent("%c%s: %s\n",
4514         first ? '/' : '|',
4515         flags & ESI_SKIPPING ? "---scanning" : "considering", s);
4516     else
4517       debug_printf_indent("%s%s: %s\n",
4518         first ? UTF8_DOWN_RIGHT : UTF8_VERT_RIGHT,
4519         flags & ESI_SKIPPING
4520         ? UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ "scanning"
4521         : "considering",
4522         s);
4523     first = FALSE;
4524     }
4525
4526   /* \ escapes the next character, which must exist, or else
4527   the expansion fails. There's a special escape, \N, which causes
4528   copying of the subject verbatim up to the next \N. Otherwise,
4529   the escapes are the standard set. */
4530
4531   if (*s == '\\')
4532     {
4533     if (s[1] == 0)
4534       {
4535       expand_string_message = US"\\ at end of string";
4536       goto EXPAND_FAILED;
4537       }
4538
4539     if (s[1] == 'N')
4540       {
4541       const uschar * t = s + 2;
4542       for (s = t; *s ; s++) if (*s == '\\' && s[1] == 'N') break;
4543
4544       DEBUG(D_expand)
4545         debug_expansion_interim(US"protected", t, (int)(s - t), !!(flags & ESI_SKIPPING));
4546       yield = string_catn(yield, t, s - t);
4547       if (*s) s += 2;
4548       }
4549     else
4550       {
4551       uschar ch[1];
4552       DEBUG(D_expand)
4553         DEBUG(D_noutf8)
4554           debug_printf_indent("|backslashed: '\\%c'\n", s[1]);
4555         else
4556           debug_printf_indent(UTF8_VERT_RIGHT "backslashed: '\\%c'\n", s[1]);
4557       ch[0] = string_interpret_escape(&s);
4558       s++;
4559       yield = string_catn(yield, ch, 1);
4560       }
4561     continue;
4562     }
4563
4564                                                                         /*{{*/
4565   /* Anything other than $ is just copied verbatim, unless we are
4566   looking for a terminating } character. */
4567
4568   if (flags & ESI_BRACE_ENDS && *s == '}') break;
4569
4570   if (*s != '$' || !(flags & ESI_HONOR_DOLLAR))
4571     {
4572     int i = 1;                                                          /*{*/
4573     for (const uschar * t = s+1;
4574         *t && *t != '$' && *t != '}' && *t != '\\'; t++) i++;
4575
4576     DEBUG(D_expand) debug_expansion_interim(US"text", s, i, !!(flags & ESI_SKIPPING));
4577
4578     yield = string_catn(yield, s, i);
4579     s += i;
4580     continue;
4581     }
4582   textonly = FALSE;
4583
4584   /* No { after the $ - must be a plain name or a number for string
4585   match variable. There has to be a fudge for variables that are the
4586   names of header fields preceded by "$header_" because header field
4587   names can contain any printing characters except space and colon.
4588   For those that don't like typing this much, "$h_" is a synonym for
4589   "$header_". A non-existent header yields a NULL value; nothing is
4590   inserted. */  /*}*/
4591
4592   if (isalpha(*++s))
4593     {
4594     const uschar * value;
4595     int newsize = 0, len;
4596     gstring * g = NULL;
4597     uschar * t;
4598
4599     s = read_name(name, sizeof(name), s, US"_");
4600
4601     /* If this is the first thing to be expanded, release the pre-allocated
4602     buffer. */
4603
4604     if (!yield)
4605       g = store_get(sizeof(gstring), GET_UNTAINTED);
4606     else if (yield->ptr == 0)
4607       {
4608       if (resetok) reset_point = store_reset(reset_point);
4609       yield = NULL;
4610       reset_point = store_mark();
4611       g = store_get(sizeof(gstring), GET_UNTAINTED);    /* alloc _before_ calling find_variable() */
4612       }
4613
4614     /* Header */
4615
4616     if (  ( *(t = name) == 'h'
4617           || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
4618           )
4619        && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
4620        )
4621       {
4622       unsigned flags = *name == 'r' ? FH_WANT_RAW
4623                       : *name == 'l' ? FH_WANT_RAW|FH_WANT_LIST
4624                       : 0;
4625       const uschar * charset = *name == 'b' ? NULL : headers_charset;
4626
4627       s = read_header_name(name, sizeof(name), s);
4628       value = find_header(name, &newsize, flags, charset);
4629
4630       /* If we didn't find the header, and the header contains a closing brace
4631       character, this may be a user error where the terminating colon
4632       has been omitted. Set a flag to adjust the error message in this case.
4633       But there is no error here - nothing gets inserted. */
4634
4635       if (!value)
4636         {                                                               /*{*/
4637         if (Ustrchr(name, '}')) malformed_header = TRUE;
4638         continue;
4639         }
4640       }
4641
4642     /* Variable */
4643
4644     else if (!(value = find_variable(name, FALSE, !!(flags & ESI_SKIPPING), &newsize)))
4645       {
4646       expand_string_message =
4647         string_sprintf("unknown variable name \"%s\"", name);
4648         check_variable_error_message(name);
4649       goto EXPAND_FAILED;
4650       }
4651
4652     /* If the data is known to be in a new buffer, newsize will be set to the
4653     size of that buffer. If this is the first thing in an expansion string,
4654     yield will be NULL; just point it at the new store instead of copying. Many
4655     expansion strings contain just one reference, so this is a useful
4656     optimization, especially for humungous headers.  We need to use a gstring
4657     structure that is not allocated after that new-buffer, else a later store
4658     reset in the middle of the buffer will make it inaccessible. */
4659
4660     len = Ustrlen(value);
4661     if (!yield && newsize != 0)
4662       {
4663       yield = g;
4664       yield->size = newsize;
4665       yield->ptr = len;
4666       yield->s = US value; /* known to be in new store i.e. a copy, so deconst safe */
4667       }
4668     else
4669       yield = string_catn(yield, value, len);
4670
4671     continue;
4672     }
4673
4674   if (isdigit(*s))
4675     {
4676     int n;
4677     s = read_cnumber(&n, s);
4678     if (n >= 0 && n <= expand_nmax)
4679       yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
4680     continue;
4681     }
4682
4683   /* Otherwise, if there's no '{' after $ it's an error. */             /*}*/
4684
4685   if (*s != '{')                                                        /*}*/
4686     {
4687     expand_string_message = US"$ not followed by letter, digit, or {";  /*}*/
4688     goto EXPAND_FAILED;
4689     }
4690
4691   /* After { there can be various things, but they all start with
4692   an initial word, except for a number for a string match variable. */  /*}*/
4693
4694   if (isdigit(*++s))
4695     {
4696     int n;
4697     s = read_cnumber(&n, s);                                            /*{{*/
4698     if (*s++ != '}')
4699       {
4700       expand_string_message = US"} expected after number";
4701       goto EXPAND_FAILED;
4702       }
4703     if (n >= 0 && n <= expand_nmax)
4704       yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
4705     continue;
4706     }
4707
4708   if (!isalpha(*s))
4709     {
4710     expand_string_message = US"letter or digit expected after ${";      /*}*/
4711     goto EXPAND_FAILED;
4712     }
4713
4714   /* Allow "-" in names to cater for substrings with negative
4715   arguments. Since we are checking for known names after { this is
4716   OK. */                                                                /*}*/
4717
4718   s = read_name(name, sizeof(name), s, US"_-");
4719   item_type = chop_match(name, item_table, nelem(item_table));
4720
4721   /* Switch on item type.  All nondefault choices should "continue* when
4722   skipping, but "break" otherwise so we get debug output for the item
4723   expansion. */
4724   {
4725   int start = gstring_length(yield);
4726   switch(item_type)
4727     {
4728     /* Call an ACL from an expansion.  We feed data in via $acl_arg1 - $acl_arg9.
4729     If the ACL returns accept or reject we return content set by "message ="
4730     There is currently no limit on recursion; this would have us call
4731     acl_check_internal() directly and get a current level from somewhere.
4732     See also the acl expansion condition ECOND_ACL and the traditional
4733     acl modifier ACLC_ACL.
4734     Assume that the function has side-effects on the store that must be preserved.
4735     */
4736
4737     case EITEM_ACL:
4738       /* ${acl {name} {arg1}{arg2}...} */
4739       {
4740       uschar * sub[10]; /* name + arg1-arg9 (which must match number of acl_arg[]) */
4741       uschar * user_msg;
4742       int rc;
4743
4744       switch(read_subs(sub, nelem(sub), 1, &s, flags, TRUE, name, &resetok, NULL))
4745         {
4746         case -1: continue;              /* skipping */
4747         case 1: goto EXPAND_FAILED_CURLY;
4748         case 2:
4749         case 3: goto EXPAND_FAILED;
4750         }
4751
4752       resetok = FALSE;
4753       switch(rc = eval_acl(sub, nelem(sub), &user_msg))
4754         {
4755         case OK:
4756         case FAIL:
4757           DEBUG(D_expand)
4758             debug_printf_indent("acl expansion yield: %s\n", user_msg);
4759           if (user_msg)
4760             yield = string_cat(yield, user_msg);
4761           break;
4762
4763         case DEFER:
4764           f.expand_string_forcedfail = TRUE;
4765           /*FALLTHROUGH*/
4766         default:
4767           expand_string_message = string_sprintf("%s from acl \"%s\"",
4768             rc_names[rc], sub[0]);
4769           goto EXPAND_FAILED;
4770         }
4771       break;
4772       }
4773
4774     case EITEM_AUTHRESULTS:
4775       /* ${authresults {mysystemname}} */
4776       {
4777       uschar * sub_arg[1];
4778
4779       switch(read_subs(sub_arg, nelem(sub_arg), 1, &s, flags, TRUE, name, &resetok, NULL))
4780         {
4781         case 1: goto EXPAND_FAILED_CURLY;
4782         case 2:
4783         case 3: goto EXPAND_FAILED;
4784         }
4785       /*XXX no skipping-optimisation? */
4786
4787       yield = string_append(yield, 3,
4788                         US"Authentication-Results: ", sub_arg[0], US"; none");
4789       yield->ptr -= 6;
4790
4791       yield = authres_local(yield, sub_arg[0]);
4792       yield = authres_iprev(yield);
4793       yield = authres_smtpauth(yield);
4794 #ifdef SUPPORT_SPF
4795       yield = authres_spf(yield);
4796 #endif
4797 #ifndef DISABLE_DKIM
4798       yield = authres_dkim(yield);
4799 #endif
4800 #ifdef SUPPORT_DMARC
4801       yield = authres_dmarc(yield);
4802 #endif
4803 #ifdef EXPERIMENTAL_ARC
4804       yield = authres_arc(yield);
4805 #endif
4806       break;
4807       }
4808
4809     /* Handle conditionals - preserve the values of the numerical expansion
4810     variables in case they get changed by a regular expression match in the
4811     condition. If not, they retain their external settings. At the end
4812     of this "if" section, they get restored to their previous values. */
4813
4814     case EITEM_IF:
4815       {
4816       BOOL cond = FALSE;
4817       const uschar *next_s;
4818       int save_expand_nmax =
4819         save_expand_strings(save_expand_nstring, save_expand_nlength);
4820       uschar * save_lookup_value = lookup_value;
4821
4822       Uskip_whitespace(&s);
4823       if (!(next_s = eval_condition(s, &resetok, flags & ESI_SKIPPING ? NULL : &cond)))
4824         goto EXPAND_FAILED;  /* message already set */
4825
4826       DEBUG(D_expand)
4827         {
4828         debug_expansion_interim(US"condition", s, (int)(next_s - s), !!(flags & ESI_SKIPPING));
4829         debug_expansion_interim(US"result",
4830           cond ? US"true" : US"false", cond ? 4 : 5, !!(flags & ESI_SKIPPING));
4831         }
4832
4833       s = next_s;
4834
4835       /* The handling of "yes" and "no" result strings is now in a separate
4836       function that is also used by ${lookup} and ${extract} and ${run}. */
4837
4838       switch(process_yesno(
4839                flags,                   /* were previously skipping */
4840                cond,                    /* success/failure indicator */
4841                lookup_value,                    /* value to reset for string2 */
4842                &s,                      /* input pointer */
4843                &yield,                  /* output pointer */
4844                US"if",                  /* condition type */
4845                &resetok))
4846         {
4847         case 1: goto EXPAND_FAILED;          /* when all is well, the */
4848         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
4849         }
4850
4851       /* Restore external setting of expansion variables for continuation
4852       at this level. */
4853
4854       lookup_value = save_lookup_value;
4855       restore_expand_strings(save_expand_nmax, save_expand_nstring,
4856         save_expand_nlength);
4857       break;
4858       }
4859
4860 #ifdef SUPPORT_I18N
4861     case EITEM_IMAPFOLDER:
4862       {                         /* ${imapfolder {name}{sep}{specials}} */
4863       uschar *sub_arg[3];
4864       uschar *encoded;
4865
4866       switch(read_subs(sub_arg, nelem(sub_arg), 1, &s, flags, TRUE, name, &resetok, NULL))
4867         {
4868         case 1: goto EXPAND_FAILED_CURLY;
4869         case 2:
4870         case 3: goto EXPAND_FAILED;
4871         }
4872       /*XXX no skipping-optimisation? */
4873
4874       if (!sub_arg[1])                  /* One argument */
4875         {
4876         sub_arg[1] = US"/";             /* default separator */
4877         sub_arg[2] = NULL;
4878         }
4879       else if (Ustrlen(sub_arg[1]) != 1)
4880         {
4881         expand_string_message =
4882           string_sprintf(
4883                 "IMAP folder separator must be one character, found \"%s\"",
4884                 sub_arg[1]);
4885         goto EXPAND_FAILED;
4886         }
4887
4888       if (flags & ESI_SKIPPING) continue;
4889
4890       if (!(encoded = imap_utf7_encode(sub_arg[0], headers_charset,
4891                           sub_arg[1][0], sub_arg[2], &expand_string_message)))
4892         goto EXPAND_FAILED;
4893       yield = string_cat(yield, encoded);
4894       break;
4895       }
4896 #endif
4897
4898     /* Handle database lookups unless locked out. If "skipping" is TRUE, we are
4899     expanding an internal string that isn't actually going to be used. All we
4900     need to do is check the syntax, so don't do a lookup at all. Preserve the
4901     values of the numerical expansion variables in case they get changed by a
4902     partial lookup. If not, they retain their external settings. At the end
4903     of this "lookup" section, they get restored to their previous values. */
4904
4905     case EITEM_LOOKUP:
4906       {
4907       int stype, partial, affixlen, starflags;
4908       int expand_setup = 0;
4909       int nameptr = 0;
4910       uschar * key, * filename;
4911       const uschar * affix, * opts;
4912       uschar * save_lookup_value = lookup_value;
4913       int save_expand_nmax =
4914         save_expand_strings(save_expand_nstring, save_expand_nlength);
4915
4916       if (expand_forbid & RDO_LOOKUP)
4917         {
4918         expand_string_message = US"lookup expansions are not permitted";
4919         goto EXPAND_FAILED;
4920         }
4921
4922       /* Get the key we are to look up for single-key+file style lookups.
4923       Otherwise set the key NULL pro-tem. */
4924
4925       if (Uskip_whitespace(&s) == '{')                                  /*}*/
4926         {
4927         key = expand_string_internal(s+1,
4928                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
4929         if (!key) goto EXPAND_FAILED;                   /*{{*/
4930         if (*s++ != '}')
4931           {
4932           expand_string_message = US"missing '}' after lookup key";
4933           goto EXPAND_FAILED_CURLY;
4934           }
4935         Uskip_whitespace(&s);
4936         }
4937       else key = NULL;
4938
4939       /* Find out the type of database */
4940
4941       if (!isalpha(*s))
4942         {
4943         expand_string_message = US"missing lookup type";
4944         goto EXPAND_FAILED;
4945         }
4946
4947       /* The type is a string that may contain special characters of various
4948       kinds. Allow everything except space or { to appear; the actual content
4949       is checked by search_findtype_partial. */         /*}*/
4950
4951       while (*s && *s != '{' && !isspace(*s))           /*}*/
4952         {
4953         if (nameptr < sizeof(name) - 1) name[nameptr++] = *s;
4954         s++;
4955         }
4956       name[nameptr] = '\0';
4957       Uskip_whitespace(&s);
4958
4959       /* Now check for the individual search type and any partial or default
4960       options. Only those types that are actually in the binary are valid. */
4961
4962       if ((stype = search_findtype_partial(name, &partial, &affix, &affixlen,
4963           &starflags, &opts)) < 0)
4964         {
4965         expand_string_message = search_error_message;
4966         goto EXPAND_FAILED;
4967         }
4968
4969       /* Check that a key was provided for those lookup types that need it,
4970       and was not supplied for those that use the query style. */
4971
4972       if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery))
4973         {
4974         if (!key)
4975           {
4976           expand_string_message = string_sprintf("missing {key} for single-"
4977             "key \"%s\" lookup", name);
4978           goto EXPAND_FAILED;
4979           }
4980         }
4981       else if (key)
4982         {
4983         expand_string_message = string_sprintf("a single key was given for "
4984           "lookup type \"%s\", which is not a single-key lookup type", name);
4985         goto EXPAND_FAILED;
4986         }
4987
4988       /* Get the next string in brackets and expand it. It is the file name for
4989       single-key+file lookups, and the whole query otherwise. In the case of
4990       queries that also require a file name (e.g. sqlite), the file name comes
4991       first. */
4992
4993       if (*s != '{')
4994         {
4995         expand_string_message = US"missing '{' for lookup file-or-query arg";
4996         goto EXPAND_FAILED_CURLY;                                               /*}}*/
4997         }
4998       if (!(filename = expand_string_internal(s+1,
4999                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL)))
5000         goto EXPAND_FAILED;
5001                                                                                 /*{{*/
5002       if (*s++ != '}')
5003         {
5004         expand_string_message = US"missing '}' closing lookup file-or-query arg";
5005         goto EXPAND_FAILED_CURLY;
5006         }
5007       Uskip_whitespace(&s);
5008
5009       /* If this isn't a single-key+file lookup, re-arrange the variables
5010       to be appropriate for the search_ functions. For query-style lookups,
5011       there is just a "key", and no file name. For the special query-style +
5012       file types, the query (i.e. "key") starts with a file name. */
5013
5014       if (!key)
5015         key = search_args(stype, name, filename, &filename, opts);
5016
5017       /* If skipping, don't do the next bit - just lookup_value == NULL, as if
5018       the entry was not found. Note that there is no search_close() function.
5019       Files are left open in case of re-use. At suitable places in higher logic,
5020       search_tidyup() is called to tidy all open files. This can save opening
5021       the same file several times. However, files may also get closed when
5022       others are opened, if too many are open at once. The rule is that a
5023       handle should not be used after a second search_open().
5024
5025       Request that a partial search sets up $1 and maybe $2 by passing
5026       expand_setup containing zero. If its value changes, reset expand_nmax,
5027       since new variables will have been set. Note that at the end of this
5028       "lookup" section, the old numeric variables are restored. */
5029
5030       if (flags & ESI_SKIPPING)
5031         lookup_value = NULL;
5032       else
5033         {
5034         void * handle = search_open(filename, stype, 0, NULL, NULL);
5035         if (!handle)
5036           {
5037           expand_string_message = search_error_message;
5038           goto EXPAND_FAILED;
5039           }
5040         lookup_value = search_find(handle, filename, key, partial, affix,
5041           affixlen, starflags, &expand_setup, opts);
5042         if (f.search_find_defer)
5043           {
5044           expand_string_message =
5045             string_sprintf("lookup of \"%s\" gave DEFER: %s",
5046               string_printing2(key, SP_TAB), search_error_message);
5047           goto EXPAND_FAILED;
5048           }
5049         if (expand_setup > 0) expand_nmax = expand_setup;
5050         }
5051
5052       /* The handling of "yes" and "no" result strings is now in a separate
5053       function that is also used by ${if} and ${extract}. */
5054
5055       switch(process_yesno(
5056                flags,                   /* were previously skipping */
5057                lookup_value != NULL,    /* success/failure indicator */
5058                save_lookup_value,       /* value to reset for string2 */
5059                &s,                      /* input pointer */
5060                &yield,                  /* output pointer */
5061                US"lookup",              /* condition type */
5062                &resetok))
5063         {
5064         case 1: goto EXPAND_FAILED;          /* when all is well, the */
5065         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
5066         }
5067
5068       /* Restore external setting of expansion variables for carrying on
5069       at this level, and continue. */
5070
5071       restore_expand_strings(save_expand_nmax, save_expand_nstring,
5072         save_expand_nlength);
5073
5074       if (flags & ESI_SKIPPING) continue;
5075       break;
5076       }
5077
5078     /* If Perl support is configured, handle calling embedded perl subroutines,
5079     unless locked out at this time. Syntax is ${perl{sub}} or ${perl{sub}{arg}}
5080     or ${perl{sub}{arg1}{arg2}} or up to a maximum of EXIM_PERL_MAX_ARGS
5081     arguments (defined below). */
5082
5083 #define EXIM_PERL_MAX_ARGS 8
5084
5085     case EITEM_PERL:
5086 #ifndef EXIM_PERL
5087       expand_string_message = US"\"${perl\" encountered, but this facility "    /*}*/
5088         "is not included in this binary";
5089       goto EXPAND_FAILED;
5090
5091 #else   /* EXIM_PERL */
5092       {
5093       uschar * sub_arg[EXIM_PERL_MAX_ARGS + 2];
5094       gstring * new_yield;
5095
5096       if (expand_forbid & RDO_PERL)
5097         {
5098         expand_string_message = US"Perl calls are not permitted";
5099         goto EXPAND_FAILED;
5100         }
5101
5102       switch(read_subs(sub_arg, EXIM_PERL_MAX_ARGS + 1, 1, &s, flags, TRUE,
5103            name, &resetok, NULL))
5104         {
5105         case -1: continue;      /* If skipping, we don't actually do anything */
5106         case 1: goto EXPAND_FAILED_CURLY;
5107         case 2:
5108         case 3: goto EXPAND_FAILED;
5109         }
5110
5111       /* Start the interpreter if necessary */
5112
5113       if (!opt_perl_started)
5114         {
5115         uschar * initerror;
5116         if (!opt_perl_startup)
5117           {
5118           expand_string_message = US"A setting of perl_startup is needed when "
5119             "using the Perl interpreter";
5120           goto EXPAND_FAILED;
5121           }
5122         DEBUG(D_any) debug_printf("Starting Perl interpreter\n");
5123         if ((initerror = init_perl(opt_perl_startup)))
5124           {
5125           expand_string_message =
5126             string_sprintf("error in perl_startup code: %s\n", initerror);
5127           goto EXPAND_FAILED;
5128           }
5129         opt_perl_started = TRUE;
5130         }
5131
5132       /* Call the function */
5133
5134       sub_arg[EXIM_PERL_MAX_ARGS + 1] = NULL;
5135       new_yield = call_perl_cat(yield, &expand_string_message,
5136         sub_arg[0], sub_arg + 1);
5137
5138       /* NULL yield indicates failure; if the message pointer has been set to
5139       NULL, the yield was undef, indicating a forced failure. Otherwise the
5140       message will indicate some kind of Perl error. */
5141
5142       if (!new_yield)
5143         {
5144         if (!expand_string_message)
5145           {
5146           expand_string_message =
5147             string_sprintf("Perl subroutine \"%s\" returned undef to force "
5148               "failure", sub_arg[0]);
5149           f.expand_string_forcedfail = TRUE;
5150           }
5151         goto EXPAND_FAILED;
5152         }
5153
5154       /* Yield succeeded. Ensure forcedfail is unset, just in case it got
5155       set during a callback from Perl. */
5156
5157       f.expand_string_forcedfail = FALSE;
5158       yield = new_yield;
5159       break;
5160       }
5161 #endif /* EXIM_PERL */
5162
5163     /* Transform email address to "prvs" scheme to use
5164        as BATV-signed return path */
5165
5166     case EITEM_PRVS:
5167       {
5168       uschar * sub_arg[3], * p, * domain;
5169
5170       switch(read_subs(sub_arg, 3, 2, &s, flags, TRUE, name, &resetok, NULL))
5171         {
5172         case -1: continue;      /* If skipping, we don't actually do anything */
5173         case 1: goto EXPAND_FAILED_CURLY;
5174         case 2:
5175         case 3: goto EXPAND_FAILED;
5176         }
5177
5178       /* sub_arg[0] is the address */
5179       if (  !(domain = Ustrrchr(sub_arg[0],'@'))
5180          || domain == sub_arg[0] || Ustrlen(domain) == 1)
5181         {
5182         expand_string_message = US"prvs first argument must be a qualified email address";
5183         goto EXPAND_FAILED;
5184         }
5185
5186       /* Calculate the hash. The third argument must be a single-digit
5187       key number, or unset. */
5188
5189       if (  sub_arg[2]
5190          && (!isdigit(sub_arg[2][0]) || sub_arg[2][1] != 0))
5191         {
5192         expand_string_message = US"prvs third argument must be a single digit";
5193         goto EXPAND_FAILED;
5194         }
5195
5196       p = prvs_hmac_sha1(sub_arg[0], sub_arg[1], sub_arg[2], prvs_daystamp(7));
5197       if (!p)
5198         {
5199         expand_string_message = US"prvs hmac-sha1 conversion failed";
5200         goto EXPAND_FAILED;
5201         }
5202
5203       /* Now separate the domain from the local part */
5204       *domain++ = '\0';
5205
5206       yield = string_catn(yield, US"prvs=", 5);
5207       yield = string_catn(yield, sub_arg[2] ? sub_arg[2] : US"0", 1);
5208       yield = string_catn(yield, prvs_daystamp(7), 3);
5209       yield = string_catn(yield, p, 6);
5210       yield = string_catn(yield, US"=", 1);
5211       yield = string_cat (yield, sub_arg[0]);
5212       yield = string_catn(yield, US"@", 1);
5213       yield = string_cat (yield, domain);
5214
5215       break;
5216       }
5217
5218     /* Check a prvs-encoded address for validity */
5219
5220     case EITEM_PRVSCHECK:
5221       {
5222       uschar * sub_arg[3], * p;
5223       gstring * g;
5224       const pcre2_code * re;
5225
5226       /* Reset expansion variables */
5227       prvscheck_result = NULL;
5228       prvscheck_address = NULL;
5229       prvscheck_keynum = NULL;
5230
5231       switch(read_subs(sub_arg, 1, 1, &s, flags, FALSE, name, &resetok, NULL))
5232         {
5233         case 1: goto EXPAND_FAILED_CURLY;
5234         case 2:
5235         case 3: goto EXPAND_FAILED;
5236         }
5237
5238       re = regex_must_compile(
5239         US"^prvs\\=([0-9])([0-9]{3})([A-F0-9]{6})\\=(.+)\\@(.+)$",
5240         MCS_CASELESS | MCS_CACHEABLE, FALSE);
5241
5242       if (regex_match_and_setup(re,sub_arg[0],0,-1))
5243         {
5244         uschar * local_part = string_copyn(expand_nstring[4],expand_nlength[4]);
5245         uschar * key_num = string_copyn(expand_nstring[1],expand_nlength[1]);
5246         uschar * daystamp = string_copyn(expand_nstring[2],expand_nlength[2]);
5247         uschar * hash = string_copyn(expand_nstring[3],expand_nlength[3]);
5248         uschar * domain = string_copyn(expand_nstring[5],expand_nlength[5]);
5249
5250         DEBUG(D_expand)
5251           {
5252           debug_printf_indent("prvscheck localpart: %s\n", local_part);
5253           debug_printf_indent("prvscheck key number: %s\n", key_num);
5254           debug_printf_indent("prvscheck daystamp: %s\n", daystamp);
5255           debug_printf_indent("prvscheck hash: %s\n", hash);
5256           debug_printf_indent("prvscheck domain: %s\n", domain);
5257           }
5258
5259         /* Set up expansion variables */
5260         g = string_cat (NULL, local_part);
5261         g = string_catn(g, US"@", 1);
5262         g = string_cat (g, domain);
5263         prvscheck_address = string_from_gstring(g);
5264         prvscheck_keynum = string_copy(key_num);
5265
5266         /* Now expand the second argument */
5267         switch(read_subs(sub_arg, 1, 1, &s, flags, FALSE, name, &resetok, NULL))
5268           {
5269           case 1: goto EXPAND_FAILED_CURLY;
5270           case 2:
5271           case 3: goto EXPAND_FAILED;
5272           }
5273
5274         /* Now we have the key and can check the address. */
5275
5276         p = prvs_hmac_sha1(prvscheck_address, sub_arg[0], prvscheck_keynum,
5277           daystamp);
5278         if (!p)
5279           {
5280           expand_string_message = US"hmac-sha1 conversion failed";
5281           goto EXPAND_FAILED;
5282           }
5283
5284         DEBUG(D_expand) debug_printf_indent("prvscheck: received hash is %s\n", hash);
5285         DEBUG(D_expand) debug_printf_indent("prvscheck:      own hash is %s\n", p);
5286
5287         if (Ustrcmp(p,hash) == 0)
5288           {
5289           /* Success, valid BATV address. Now check the expiry date. */
5290           uschar *now = prvs_daystamp(0);
5291           unsigned int inow = 0,iexpire = 1;
5292
5293           (void)sscanf(CS now,"%u",&inow);
5294           (void)sscanf(CS daystamp,"%u",&iexpire);
5295
5296           /* When "iexpire" is < 7, a "flip" has occurred.
5297              Adjust "inow" accordingly. */
5298           if ( (iexpire < 7) && (inow >= 993) ) inow = 0;
5299
5300           if (iexpire >= inow)
5301             {
5302             prvscheck_result = US"1";
5303             DEBUG(D_expand) debug_printf_indent("prvscheck: success, $pvrs_result set to 1\n");
5304             }
5305           else
5306             {
5307             prvscheck_result = NULL;
5308             DEBUG(D_expand) debug_printf_indent("prvscheck: signature expired, $pvrs_result unset\n");
5309             }
5310           }
5311         else
5312           {
5313           prvscheck_result = NULL;
5314           DEBUG(D_expand) debug_printf_indent("prvscheck: hash failure, $pvrs_result unset\n");
5315           }
5316
5317         /* Now expand the final argument. We leave this till now so that
5318         it can include $prvscheck_result. */
5319
5320         switch(read_subs(sub_arg, 1, 0, &s, flags, TRUE, name, &resetok, NULL))
5321           {
5322           case 1: goto EXPAND_FAILED_CURLY;
5323           case 2:
5324           case 3: goto EXPAND_FAILED;
5325           }
5326
5327         yield = string_cat(yield,
5328           !sub_arg[0] || !*sub_arg[0] ? prvscheck_address : sub_arg[0]);
5329
5330         /* Reset the "internal" variables afterwards, because they are in
5331         dynamic store that will be reclaimed if the expansion succeeded. */
5332
5333         prvscheck_address = NULL;
5334         prvscheck_keynum = NULL;
5335         }
5336       else
5337         /* Does not look like a prvs encoded address, return the empty string.
5338            We need to make sure all subs are expanded first, so as to skip over
5339            the entire item. */
5340
5341         switch(read_subs(sub_arg, 2, 1, &s, flags, TRUE, name, &resetok, NULL))
5342           {
5343           case 1: goto EXPAND_FAILED_CURLY;
5344           case 2:
5345           case 3: goto EXPAND_FAILED;
5346           }
5347
5348       if (flags & ESI_SKIPPING) continue;
5349       break;
5350       }
5351
5352     /* Handle "readfile" to insert an entire file */
5353
5354     case EITEM_READFILE:
5355       {
5356       FILE * f;
5357       uschar * sub_arg[2];
5358
5359       if ((expand_forbid & RDO_READFILE) != 0)
5360         {
5361         expand_string_message = US"file insertions are not permitted";
5362         goto EXPAND_FAILED;
5363         }
5364
5365       switch(read_subs(sub_arg, 2, 1, &s, flags, TRUE, name, &resetok, NULL))
5366         {
5367         case 1: goto EXPAND_FAILED_CURLY;
5368         case 2:
5369         case 3: goto EXPAND_FAILED;
5370         }
5371
5372       /* If skipping, we don't actually do anything */
5373
5374       if (flags & ESI_SKIPPING) continue;
5375
5376       /* Open the file and read it */
5377
5378       if (!(f = Ufopen(sub_arg[0], "rb")))
5379         {
5380         expand_string_message = string_open_failed("%s", sub_arg[0]);
5381         goto EXPAND_FAILED;
5382         }
5383
5384       yield = cat_file(f, yield, sub_arg[1]);
5385       (void)fclose(f);
5386       break;
5387       }
5388
5389     /* Handle "readsocket" to insert data from a socket, either
5390     Inet or Unix domain */
5391
5392     case EITEM_READSOCK:
5393       {
5394       uschar * arg;
5395       uschar * sub_arg[4];
5396
5397       if (expand_forbid & RDO_READSOCK)
5398         {
5399         expand_string_message = US"socket insertions are not permitted";
5400         goto EXPAND_FAILED;
5401         }
5402
5403       /* Read up to 4 arguments, but don't do the end of item check afterwards,
5404       because there may be a string for expansion on failure. */
5405
5406       switch(read_subs(sub_arg, 4, 2, &s, flags, FALSE, name, &resetok, NULL))
5407         {
5408         case 1: goto EXPAND_FAILED_CURLY;
5409         case 2:                             /* Won't occur: no end check */
5410         case 3: goto EXPAND_FAILED;
5411         }
5412
5413       /* If skipping, we don't actually do anything. Otherwise, arrange to
5414       connect to either an IP or a Unix socket. */
5415
5416       if (!(flags & ESI_SKIPPING))
5417         {
5418         int stype = search_findtype(US"readsock", 8);
5419         gstring * g = NULL;
5420         void * handle;
5421         int expand_setup = -1;
5422         uschar * s;
5423
5424         /* If the reqstr is empty, flag that and set a dummy */
5425
5426         if (!sub_arg[1][0])
5427           {
5428           g = string_append_listele(g, ',', US"send=no");
5429           sub_arg[1] = US"DUMMY";
5430           }
5431
5432         /* Re-marshall the options */
5433
5434         if (sub_arg[2])
5435           {
5436           const uschar * list = sub_arg[2];
5437           uschar * item;
5438           int sep = 0;
5439
5440           /* First option has no tag and is timeout */
5441           if ((item = string_nextinlist(&list, &sep, NULL, 0)))
5442             g = string_append_listele(g, ',',
5443                   string_sprintf("timeout=%s", item));
5444
5445           /* The rest of the options from the expansion */
5446           while ((item = string_nextinlist(&list, &sep, NULL, 0)))
5447             g = string_append_listele(g, ',', item);
5448
5449           /* possibly plus an EOL string.  Process with escapes, to protect
5450           from list-processing.  The only current user of eol= in search
5451           options is the readsock expansion. */
5452
5453           if (sub_arg[3] && *sub_arg[3])
5454             g = string_append_listele(g, ',',
5455                   string_sprintf("eol=%s",
5456                     string_printing2(sub_arg[3], SP_TAB|SP_SPACE)));
5457           }
5458
5459         /* Gat a (possibly cached) handle for the connection */
5460
5461         if (!(handle = search_open(sub_arg[0], stype, 0, NULL, NULL)))
5462           {
5463           if (*expand_string_message) goto EXPAND_FAILED;
5464           expand_string_message = search_error_message;
5465           search_error_message = NULL;
5466           goto SOCK_FAIL;
5467           }
5468
5469         /* Get (possibly cached) results for the lookup */
5470         /* sspec: sub_arg[0]  req: sub_arg[1]  opts: g */
5471
5472         if ((s = search_find(handle, sub_arg[0], sub_arg[1], -1, NULL, 0, 0,
5473                                     &expand_setup, string_from_gstring(g))))
5474           yield = string_cat(yield, s);
5475         else if (f.search_find_defer)
5476           {
5477           expand_string_message = search_error_message;
5478           search_error_message = NULL;
5479           goto SOCK_FAIL;
5480           }
5481         else
5482           {     /* should not happen, at present */
5483           expand_string_message = search_error_message;
5484           search_error_message = NULL;
5485           goto SOCK_FAIL;
5486           }
5487         }
5488
5489       /* The whole thing has worked (or we were skipping). If there is a
5490       failure string following, we need to skip it. */
5491
5492       if (*s == '{')                                                    /*}*/
5493         {
5494         if (!expand_string_internal(s+1,
5495           ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | ESI_SKIPPING, &s, &resetok, NULL))
5496           goto EXPAND_FAILED;                                           /*{*/
5497         if (*s++ != '}')
5498           {                                                             /*{*/
5499           expand_string_message = US"missing '}' closing failstring for readsocket";
5500           goto EXPAND_FAILED_CURLY;
5501           }
5502         Uskip_whitespace(&s);
5503         }
5504
5505     READSOCK_DONE:                                                      /*{*/
5506       if (*s++ != '}')
5507         {                                                               /*{*/
5508         expand_string_message = US"missing '}' closing readsocket";
5509         goto EXPAND_FAILED_CURLY;
5510         }
5511       if (flags & ESI_SKIPPING) continue;
5512       break;
5513
5514       /* Come here on failure to create socket, connect socket, write to the
5515       socket, or timeout on reading. If another substring follows, expand and
5516       use it. Otherwise, those conditions give expand errors. */
5517
5518     SOCK_FAIL:
5519       if (*s != '{') goto EXPAND_FAILED;                                /*}*/
5520       DEBUG(D_any) debug_printf("%s\n", expand_string_message);
5521       if (!(arg = expand_string_internal(s+1,
5522                     ESI_BRACE_ENDS | ESI_HONOR_DOLLAR, &s, &resetok, NULL)))
5523         goto EXPAND_FAILED;
5524       yield = string_cat(yield, arg);                                   /*{*/
5525       if (*s++ != '}')
5526         {                                                               /*{*/
5527         expand_string_message = US"missing '}' closing failstring for readsocket";
5528         goto EXPAND_FAILED_CURLY;
5529         }
5530       Uskip_whitespace(&s);
5531       goto READSOCK_DONE;
5532       }
5533
5534     /* Handle "run" to execute a program. */
5535
5536     case EITEM_RUN:
5537       {
5538       FILE * f;
5539       const uschar * arg, ** argv;
5540       BOOL late_expand = TRUE;
5541
5542       if ((expand_forbid & RDO_RUN) != 0)
5543         {
5544         expand_string_message = US"running a command is not permitted";
5545         goto EXPAND_FAILED;
5546         }
5547
5548       /* Handle options to the "run" */
5549
5550       while (*s == ',')
5551         {
5552         if (Ustrncmp(++s, "preexpand", 9) == 0)
5553           { late_expand = FALSE; s += 9; }
5554         else
5555           {
5556           const uschar * t = s;
5557           while (isalpha(*++t)) ;
5558           expand_string_message = string_sprintf("bad option '%.*s' for run",
5559                                                   (int)(t-s), s);
5560           goto EXPAND_FAILED;
5561           }
5562         }
5563       Uskip_whitespace(&s);
5564
5565       if (*s != '{')                                    /*}*/
5566         {
5567         expand_string_message = US"missing '{' for command arg of run";
5568         goto EXPAND_FAILED_CURLY;                       /*"}*/
5569         }
5570       s++;
5571
5572       if (late_expand)          /* this is the default case */
5573         {                                               /*{*/
5574         int n = Ustrcspn(s, "}");
5575         arg = flags & ESI_SKIPPING ? NULL : string_copyn(s, n);
5576         s += n;
5577         }
5578       else
5579         {
5580         if (!(arg = expand_string_internal(s,
5581                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL)))
5582           goto EXPAND_FAILED;
5583         Uskip_whitespace(&s);
5584         }
5585                                                         /*{*/
5586       if (*s++ != '}')
5587         {                                               /*{*/
5588         expand_string_message = US"missing '}' closing command arg of run";
5589         goto EXPAND_FAILED_CURLY;
5590         }
5591
5592       if (flags & ESI_SKIPPING)   /* Just pretend it worked when we're skipping */
5593         {
5594         runrc = 0;
5595         lookup_value = NULL;
5596         }
5597       else
5598         {
5599         int fd_in, fd_out;
5600         pid_t pid;
5601
5602         if (!transport_set_up_command(&argv,    /* anchor for arg list */
5603             arg,                                /* raw command */
5604             late_expand,                /* expand args if not already done */
5605             0,                          /* not relevant when... */
5606             NULL,                       /* no transporting address */
5607             late_expand,                /* allow tainted args, when expand-after-split */
5608             US"${run} expansion",       /* for error messages */
5609             &expand_string_message))    /* where to put error message */
5610           goto EXPAND_FAILED;
5611
5612         /* Create the child process, making it a group leader. */
5613
5614         if ((pid = child_open(USS argv, NULL, 0077, &fd_in, &fd_out, TRUE,
5615                               US"expand-run")) < 0)
5616           {
5617           expand_string_message =
5618             string_sprintf("couldn't create child process: %s", strerror(errno));
5619           goto EXPAND_FAILED;
5620           }
5621
5622         /* Nothing is written to the standard input. */
5623
5624         (void)close(fd_in);
5625
5626         /* Read the pipe to get the command's output into $value (which is kept
5627         in lookup_value). Read during execution, so that if the output exceeds
5628         the OS pipe buffer limit, we don't block forever. Remember to not release
5629         memory just allocated for $value. */
5630
5631         resetok = FALSE;
5632         f = fdopen(fd_out, "rb");
5633         sigalrm_seen = FALSE;
5634         ALARM(60);
5635         lookup_value = string_from_gstring(cat_file(f, NULL, NULL));
5636         ALARM_CLR(0);
5637         (void)fclose(f);
5638
5639         /* Wait for the process to finish, applying the timeout, and inspect its
5640         return code for serious disasters. Simple non-zero returns are passed on.
5641         */
5642
5643         if (sigalrm_seen || (runrc = child_close(pid, 30)) < 0)
5644           {
5645           if (sigalrm_seen || runrc == -256)
5646             {
5647             expand_string_message = US"command timed out";
5648             killpg(pid, SIGKILL);       /* Kill the whole process group */
5649             }
5650
5651           else if (runrc == -257)
5652             expand_string_message = string_sprintf("wait() failed: %s",
5653               strerror(errno));
5654
5655           else
5656             expand_string_message = string_sprintf("command killed by signal %d",
5657               -runrc);
5658
5659           goto EXPAND_FAILED;
5660           }
5661         }
5662
5663       /* Process the yes/no strings; $value may be useful in both cases */
5664
5665       switch(process_yesno(
5666                flags,                   /* were previously skipping */
5667                runrc == 0,              /* success/failure indicator */
5668                lookup_value,            /* value to reset for string2 */
5669                &s,                      /* input pointer */
5670                &yield,                  /* output pointer */
5671                US"run",                 /* condition type */
5672                &resetok))
5673         {
5674         case 1: goto EXPAND_FAILED;          /* when all is well, the */
5675         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
5676         }
5677
5678       if (flags & ESI_SKIPPING) continue;
5679       break;
5680       }
5681
5682     /* Handle character translation for "tr" */
5683
5684     case EITEM_TR:
5685       {
5686       int oldptr = gstring_length(yield);
5687       int o2m;
5688       uschar * sub[3];
5689
5690       switch(read_subs(sub, 3, 3, &s, flags, TRUE, name, &resetok, NULL))
5691         {
5692         case -1: continue;      /* skipping */
5693         case 1: goto EXPAND_FAILED_CURLY;
5694         case 2:
5695         case 3: goto EXPAND_FAILED;
5696         }
5697
5698       yield = string_cat(yield, sub[0]);
5699       o2m = Ustrlen(sub[2]) - 1;
5700
5701       if (o2m >= 0) for (; oldptr < yield->ptr; oldptr++)
5702         {
5703         uschar *m = Ustrrchr(sub[1], yield->s[oldptr]);
5704         if (m)
5705           {
5706           int o = m - sub[1];
5707           yield->s[oldptr] = sub[2][(o < o2m)? o : o2m];
5708           }
5709         }
5710
5711       break;
5712       }
5713
5714     /* Handle "hash", "length", "nhash", and "substr" when they are given with
5715     expanded arguments. */
5716
5717     case EITEM_HASH:
5718     case EITEM_LENGTH:
5719     case EITEM_NHASH:
5720     case EITEM_SUBSTR:
5721       {
5722       int len;
5723       uschar *ret;
5724       int val[2] = { 0, -1 };
5725       uschar * sub[3];
5726
5727       /* "length" takes only 2 arguments whereas the others take 2 or 3.
5728       Ensure that sub[2] is set in the ${length } case. */
5729
5730       sub[2] = NULL;
5731       switch(read_subs(sub, item_type == EITEM_LENGTH ? 2:3, 2, &s, flags,
5732              TRUE, name, &resetok, NULL))
5733         {
5734         case -1: continue;      /* skipping */
5735         case 1: goto EXPAND_FAILED_CURLY;
5736         case 2:
5737         case 3: goto EXPAND_FAILED;
5738         }
5739
5740       /* Juggle the arguments if there are only two of them: always move the
5741       string to the last position and make ${length{n}{str}} equivalent to
5742       ${substr{0}{n}{str}}. See the defaults for val[] above. */
5743
5744       if (!sub[2])
5745         {
5746         sub[2] = sub[1];
5747         sub[1] = NULL;
5748         if (item_type == EITEM_LENGTH)
5749           {
5750           sub[1] = sub[0];
5751           sub[0] = NULL;
5752           }
5753         }
5754
5755       for (int i = 0; i < 2; i++) if (sub[i])
5756         {
5757         val[i] = (int)Ustrtol(sub[i], &ret, 10);
5758         if (*ret != 0 || (i != 0 && val[i] < 0))
5759           {
5760           expand_string_message = string_sprintf("\"%s\" is not a%s number "
5761             "(in \"%s\" expansion)", sub[i], (i != 0)? " positive" : "", name);
5762           goto EXPAND_FAILED;
5763           }
5764         }
5765
5766       ret =
5767         item_type == EITEM_HASH
5768         ?  compute_hash(sub[2], val[0], val[1], &len)
5769         : item_type == EITEM_NHASH
5770         ? compute_nhash(sub[2], val[0], val[1], &len)
5771         : extract_substr(sub[2], val[0], val[1], &len);
5772       if (!ret)
5773         goto EXPAND_FAILED;
5774       yield = string_catn(yield, ret, len);
5775       break;
5776       }
5777
5778     /* Handle HMAC computation: ${hmac{<algorithm>}{<secret>}{<text>}}
5779     This code originally contributed by Steve Haslam. It currently supports
5780     the use of MD5 and SHA-1 hashes.
5781
5782     We need some workspace that is large enough to handle all the supported
5783     hash types. Use macros to set the sizes rather than be too elaborate. */
5784
5785     #define MAX_HASHLEN      20
5786     #define MAX_HASHBLOCKLEN 64
5787
5788     case EITEM_HMAC:
5789       {
5790       uschar * sub[3];
5791       md5 md5_base;
5792       hctx sha1_ctx;
5793       void * use_base;
5794       int type;
5795       int hashlen;      /* Number of octets for the hash algorithm's output */
5796       int hashblocklen; /* Number of octets the hash algorithm processes */
5797       uschar * keyptr, * p;
5798       unsigned int keylen;
5799
5800       uschar keyhash[MAX_HASHLEN];
5801       uschar innerhash[MAX_HASHLEN];
5802       uschar finalhash[MAX_HASHLEN];
5803       uschar finalhash_hex[2*MAX_HASHLEN];
5804       uschar innerkey[MAX_HASHBLOCKLEN];
5805       uschar outerkey[MAX_HASHBLOCKLEN];
5806
5807       switch (read_subs(sub, 3, 3, &s, flags, TRUE, name, &resetok, NULL))
5808         {
5809         case -1: continue;      /* skipping */
5810         case 1: goto EXPAND_FAILED_CURLY;
5811         case 2:
5812         case 3: goto EXPAND_FAILED;
5813         }
5814
5815       if (Ustrcmp(sub[0], "md5") == 0)
5816         {
5817         type = HMAC_MD5;
5818         use_base = &md5_base;
5819         hashlen = 16;
5820         hashblocklen = 64;
5821         }
5822       else if (Ustrcmp(sub[0], "sha1") == 0)
5823         {
5824         type = HMAC_SHA1;
5825         use_base = &sha1_ctx;
5826         hashlen = 20;
5827         hashblocklen = 64;
5828         }
5829       else
5830         {
5831         expand_string_message =
5832           string_sprintf("hmac algorithm \"%s\" is not recognised", sub[0]);
5833         goto EXPAND_FAILED;
5834         }
5835
5836       keyptr = sub[1];
5837       keylen = Ustrlen(keyptr);
5838
5839       /* If the key is longer than the hash block length, then hash the key
5840       first */
5841
5842       if (keylen > hashblocklen)
5843         {
5844         chash_start(type, use_base);
5845         chash_end(type, use_base, keyptr, keylen, keyhash);
5846         keyptr = keyhash;
5847         keylen = hashlen;
5848         }
5849
5850       /* Now make the inner and outer key values */
5851
5852       memset(innerkey, 0x36, hashblocklen);
5853       memset(outerkey, 0x5c, hashblocklen);
5854
5855       for (int i = 0; i < keylen; i++)
5856         {
5857         innerkey[i] ^= keyptr[i];
5858         outerkey[i] ^= keyptr[i];
5859         }
5860
5861       /* Now do the hashes */
5862
5863       chash_start(type, use_base);
5864       chash_mid(type, use_base, innerkey);
5865       chash_end(type, use_base, sub[2], Ustrlen(sub[2]), innerhash);
5866
5867       chash_start(type, use_base);
5868       chash_mid(type, use_base, outerkey);
5869       chash_end(type, use_base, innerhash, hashlen, finalhash);
5870
5871       /* Encode the final hash as a hex string */
5872
5873       p = finalhash_hex;
5874       for (int i = 0; i < hashlen; i++)
5875         {
5876         *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
5877         *p++ = hex_digits[finalhash[i] & 0x0f];
5878         }
5879
5880       DEBUG(D_any) debug_printf("HMAC[%s](%.*s,%s)=%.*s\n",
5881         sub[0], (int)keylen, keyptr, sub[2], hashlen*2, finalhash_hex);
5882
5883       yield = string_catn(yield, finalhash_hex, hashlen*2);
5884       break;
5885       }
5886
5887     /* Handle global substitution for "sg" - like Perl's s/xxx/yyy/g operator.
5888     We have to save the numerical variables and restore them afterwards. */
5889
5890     case EITEM_SG:
5891       {
5892       const pcre2_code * re;
5893       int moffset, moffsetextra, slen;
5894       pcre2_match_data * md;
5895       int emptyopt;
5896       uschar * subject, * sub[3];
5897       int save_expand_nmax =
5898         save_expand_strings(save_expand_nstring, save_expand_nlength);
5899       unsigned sub_textonly = 0;
5900
5901       switch(read_subs(sub, 3, 3, &s, flags, TRUE, name, &resetok, &sub_textonly))
5902         {
5903         case -1: continue;      /* skipping */
5904         case 1: goto EXPAND_FAILED_CURLY;
5905         case 2:
5906         case 3: goto EXPAND_FAILED;
5907         }
5908
5909       /* Compile the regular expression */
5910
5911       re = regex_compile(sub[1],
5912               sub_textonly & BIT(1) ? MCS_CACHEABLE : MCS_NOFLAGS,
5913               &expand_string_message, pcre_gen_cmp_ctx);
5914       if (!re)
5915         goto EXPAND_FAILED;
5916
5917       md = pcre2_match_data_create(EXPAND_MAXN + 1, pcre_gen_ctx);
5918
5919       /* Now run a loop to do the substitutions as often as necessary. It ends
5920       when there are no more matches. Take care over matches of the null string;
5921       do the same thing as Perl does. */
5922
5923       subject = sub[0];
5924       slen = Ustrlen(sub[0]);
5925       moffset = moffsetextra = 0;
5926       emptyopt = 0;
5927
5928       for (;;)
5929         {
5930         PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
5931         int n = pcre2_match(re, (PCRE2_SPTR)subject, slen, moffset + moffsetextra,
5932           PCRE_EOPT | emptyopt, md, pcre_gen_mtc_ctx);
5933         uschar * insert;
5934
5935         /* No match - if we previously set PCRE_NOTEMPTY after a null match, this
5936         is not necessarily the end. We want to repeat the match from one
5937         character further along, but leaving the basic offset the same (for
5938         copying below). We can't be at the end of the string - that was checked
5939         before setting PCRE_NOTEMPTY. If PCRE_NOTEMPTY is not set, we are
5940         finished; copy the remaining string and end the loop. */
5941
5942         if (n < 0)
5943           {
5944           if (emptyopt != 0)
5945             {
5946             moffsetextra = 1;
5947             emptyopt = 0;
5948             continue;
5949             }
5950           yield = string_catn(yield, subject+moffset, slen-moffset);
5951           break;
5952           }
5953
5954         /* Match - set up for expanding the replacement. */
5955         DEBUG(D_expand) debug_printf_indent("%s: match\n", name);
5956
5957         if (n == 0) n = EXPAND_MAXN + 1;
5958         expand_nmax = 0;
5959         for (int nn = 0; nn < n*2; nn += 2)
5960           {
5961           expand_nstring[expand_nmax] = subject + ovec[nn];
5962           expand_nlength[expand_nmax++] = ovec[nn+1] - ovec[nn];
5963           }
5964         expand_nmax--;
5965
5966         /* Copy the characters before the match, plus the expanded insertion. */
5967
5968         yield = string_catn(yield, subject + moffset, ovec[0] - moffset);
5969
5970         if (!(insert = expand_string(sub[2])))
5971           goto EXPAND_FAILED;
5972         yield = string_cat(yield, insert);
5973
5974         moffset = ovec[1];
5975         moffsetextra = 0;
5976         emptyopt = 0;
5977
5978         /* If we have matched an empty string, first check to see if we are at
5979         the end of the subject. If so, the loop is over. Otherwise, mimic
5980         what Perl's /g options does. This turns out to be rather cunning. First
5981         we set PCRE_NOTEMPTY and PCRE_ANCHORED and try the match a non-empty
5982         string at the same point. If this fails (picked up above) we advance to
5983         the next character. */
5984
5985         if (ovec[0] == ovec[1])
5986           {
5987           if (ovec[0] == slen) break;
5988           emptyopt = PCRE2_NOTEMPTY | PCRE2_ANCHORED;
5989           }
5990         }
5991
5992       /* All done - restore numerical variables. */
5993
5994       /* pcre2_match_data_free(md);     gen ctx needs no free */
5995       restore_expand_strings(save_expand_nmax, save_expand_nstring,
5996         save_expand_nlength);
5997       break;
5998       }
5999
6000     /* Handle keyed and numbered substring extraction. If the first argument
6001     consists entirely of digits, then a numerical extraction is assumed. */
6002
6003     case EITEM_EXTRACT:
6004       {
6005       int field_number = 1;
6006       BOOL field_number_set = FALSE;
6007       uschar * save_lookup_value = lookup_value, * sub[3];
6008       int save_expand_nmax =
6009         save_expand_strings(save_expand_nstring, save_expand_nlength);
6010
6011       /* On reflection the original behaviour of extract-json for a string
6012       result, leaving it quoted, was a mistake.  But it was already published,
6013       hence the addition of jsons.  In a future major version, make json
6014       work like josons, and withdraw jsons. */
6015
6016       enum {extract_basic, extract_json, extract_jsons} fmt = extract_basic;
6017
6018       /* Check for a format-variant specifier */
6019
6020       if (Uskip_whitespace(&s) != '{')                                  /*}*/
6021         if (Ustrncmp(s, "json", 4) == 0)
6022           if (*(s += 4) == 's')
6023             {fmt = extract_jsons; s++;}
6024           else
6025             fmt = extract_json;
6026
6027       /* While skipping we cannot rely on the data for expansions being
6028       available (eg. $item) hence cannot decide on numeric vs. keyed.
6029       Read a maximum of 5 arguments (including the yes/no) */
6030
6031       if (flags & ESI_SKIPPING)
6032         {
6033         for (int j = 5; j > 0 && *s == '{'; j--)                        /*'}'*/
6034           {
6035           if (!expand_string_internal(s+1,
6036                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL))
6037             goto EXPAND_FAILED;                                 /*'{'*/
6038           if (*s++ != '}')
6039             {
6040             expand_string_message = US"missing '{' for arg of extract";
6041             goto EXPAND_FAILED_CURLY;
6042             }
6043           Uskip_whitespace(&s);
6044           }
6045         if (  Ustrncmp(s, "fail", 4) == 0                               /*'{'*/
6046            && (s[4] == '}' || s[4] == ' ' || s[4] == '\t' || !s[4])
6047            )
6048           {
6049           s += 4;
6050           Uskip_whitespace(&s);
6051           }                                                             /*'{'*/
6052         if (*s != '}')
6053           {
6054           expand_string_message = US"missing '}' closing extract";
6055           goto EXPAND_FAILED_CURLY;
6056           }
6057         }
6058
6059       else for (int i = 0, j = 2; i < j; i++) /* Read the proper number of arguments */
6060         {
6061         if (Uskip_whitespace(&s) == '{')                                /*'}'*/
6062           {
6063           if (!(sub[i] = expand_string_internal(s+1,
6064                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL)))
6065             goto EXPAND_FAILED;                                         /*'{'*/
6066           if (*s++ != '}')
6067             {
6068             expand_string_message = string_sprintf(
6069               "missing '}' closing arg %d of extract", i+1);
6070             goto EXPAND_FAILED_CURLY;
6071             }
6072
6073           /* After removal of leading and trailing white space, the first
6074           argument must not be empty; if it consists entirely of digits
6075           (optionally preceded by a minus sign), this is a numerical
6076           extraction, and we expect 3 arguments (normal) or 2 (json). */
6077
6078           if (i == 0)
6079             {
6080             int len;
6081             int x = 0;
6082             uschar * p = sub[0];
6083
6084             Uskip_whitespace(&p);
6085             sub[0] = p;
6086
6087             len = Ustrlen(p);
6088             while (len > 0 && isspace(p[len-1])) len--;
6089             p[len] = 0;
6090
6091             if (!*p)
6092               {
6093               expand_string_message = US"first argument of \"extract\" must "
6094                 "not be empty";
6095               goto EXPAND_FAILED;
6096               }
6097
6098             if (*p == '-')
6099               {
6100               field_number = -1;
6101               p++;
6102               }
6103             while (*p && isdigit(*p)) x = x * 10 + *p++ - '0';
6104             if (!*p)
6105               {
6106               field_number *= x;
6107               if (fmt == extract_basic) j = 3;               /* Need 3 args */
6108               field_number_set = TRUE;
6109               }
6110             }
6111           }
6112         else
6113           {
6114           expand_string_message = string_sprintf(
6115             "missing '{' for arg %d of extract", i+1);
6116           goto EXPAND_FAILED_CURLY;
6117           }
6118         }
6119
6120       /* Extract either the numbered or the keyed substring into $value. If
6121       skipping, just pretend the extraction failed. */
6122
6123       if (flags & ESI_SKIPPING)
6124         lookup_value = NULL;
6125       else switch (fmt)
6126         {
6127         case extract_basic:
6128           lookup_value = field_number_set
6129             ? expand_gettokened(field_number, sub[1], sub[2])
6130             : expand_getkeyed(sub[0], sub[1]);
6131           break;
6132
6133         case extract_json:
6134         case extract_jsons:
6135           {
6136           uschar * s, * item;
6137           const uschar * list;
6138
6139           /* Array: Bracket-enclosed and comma-separated.
6140           Object: Brace-enclosed, comma-sep list of name:value pairs */
6141
6142           if (!(s = dewrap(sub[1], field_number_set ? US"[]" : US"{}")))
6143             {
6144             expand_string_message =
6145               string_sprintf("%s wrapping %s for extract json",
6146                 expand_string_message,
6147                 field_number_set ? "array" : "object");
6148             goto EXPAND_FAILED_CURLY;
6149             }
6150
6151           list = s;
6152           if (field_number_set)
6153             {
6154             if (field_number <= 0)
6155               {
6156               expand_string_message = US"first argument of \"extract\" must "
6157                 "be greater than zero";
6158               goto EXPAND_FAILED;
6159               }
6160             while (field_number > 0 && (item = json_nextinlist(&list)))
6161               field_number--;
6162             if ((lookup_value = s = item))
6163               {
6164               while (*s) s++;
6165               while (--s >= lookup_value && isspace(*s)) *s = '\0';
6166               }
6167             }
6168           else
6169             {
6170             lookup_value = NULL;
6171             while ((item = json_nextinlist(&list)))
6172               {
6173               /* Item is:  string name-sep value.  string is quoted.
6174               Dequote the string and compare with the search key. */
6175
6176               if (!(item = dewrap(item, US"\"\"")))
6177                 {
6178                 expand_string_message =
6179                   string_sprintf("%s wrapping string key for extract json",
6180                     expand_string_message);
6181                 goto EXPAND_FAILED_CURLY;
6182                 }
6183               if (Ustrcmp(item, sub[0]) == 0)   /*XXX should be a UTF8-compare */
6184                 {
6185                 s = item + Ustrlen(item) + 1;
6186                 if (Uskip_whitespace(&s) != ':')
6187                   {
6188                   expand_string_message =
6189                     US"missing object value-separator for extract json";
6190                   goto EXPAND_FAILED_CURLY;
6191                   }
6192                 s++;
6193                 Uskip_whitespace(&s);
6194                 lookup_value = s;
6195                 break;
6196                 }
6197               }
6198             }
6199           }
6200
6201           if (  fmt == extract_jsons
6202              && lookup_value
6203              && !(lookup_value = dewrap(lookup_value, US"\"\"")))
6204             {
6205             expand_string_message =
6206               string_sprintf("%s wrapping string result for extract jsons",
6207                 expand_string_message);
6208             goto EXPAND_FAILED_CURLY;
6209             }
6210           break;        /* json/s */
6211         }
6212
6213       /* If no string follows, $value gets substituted; otherwise there can
6214       be yes/no strings, as for lookup or if. */
6215
6216       switch(process_yesno(
6217                flags,                   /* were previously skipping */
6218                lookup_value != NULL,    /* success/failure indicator */
6219                save_lookup_value,       /* value to reset for string2 */
6220                &s,                      /* input pointer */
6221                &yield,                  /* output pointer */
6222                US"extract",             /* condition type */
6223                &resetok))
6224         {
6225         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6226         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6227         }
6228
6229       /* All done - restore numerical variables. */
6230
6231       restore_expand_strings(save_expand_nmax, save_expand_nstring,
6232         save_expand_nlength);
6233
6234       if (flags & ESI_SKIPPING) continue;
6235       break;
6236       }
6237
6238     /* return the Nth item from a list */
6239
6240     case EITEM_LISTEXTRACT:
6241       {
6242       int field_number = 1;
6243       uschar * save_lookup_value = lookup_value, * sub[2];
6244       int save_expand_nmax =
6245         save_expand_strings(save_expand_nstring, save_expand_nlength);
6246
6247       /* Read the field & list arguments */
6248
6249       for (int i = 0; i < 2; i++)
6250         {
6251         if (Uskip_whitespace(&s) != '{')                                /*}*/
6252           {
6253           expand_string_message = string_sprintf(
6254             "missing '{' for arg %d of listextract", i+1);              /*}*/
6255           goto EXPAND_FAILED_CURLY;
6256           }
6257
6258         sub[i] = expand_string_internal(s+1,
6259               ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
6260         if (!sub[i])     goto EXPAND_FAILED;                            /*{{*/
6261         if (*s++ != '}')
6262           {
6263           expand_string_message = string_sprintf(
6264             "missing '}' closing arg %d of listextract", i+1);
6265           goto EXPAND_FAILED_CURLY;
6266           }
6267
6268         /* After removal of leading and trailing white space, the first
6269         argument must be numeric and nonempty. */
6270
6271         if (i == 0)
6272           {
6273           int len;
6274           int x = 0;
6275           uschar *p = sub[0];
6276
6277           Uskip_whitespace(&p);
6278           sub[0] = p;
6279
6280           len = Ustrlen(p);
6281           while (len > 0 && isspace(p[len-1])) len--;
6282           p[len] = 0;
6283
6284           if (!*p && !(flags & ESI_SKIPPING))
6285             {
6286             expand_string_message = US"first argument of \"listextract\" must "
6287               "not be empty";
6288             goto EXPAND_FAILED;
6289             }
6290
6291           if (*p == '-')
6292             {
6293             field_number = -1;
6294             p++;
6295             }
6296           while (*p && isdigit(*p)) x = x * 10 + *p++ - '0';
6297           if (*p)
6298             {
6299             expand_string_message = US"first argument of \"listextract\" must "
6300               "be numeric";
6301             goto EXPAND_FAILED;
6302             }
6303           field_number *= x;
6304           }
6305         }
6306
6307       /* Extract the numbered element into $value. If
6308       skipping, just pretend the extraction failed. */
6309
6310       lookup_value = flags & ESI_SKIPPING ? NULL : expand_getlistele(field_number, sub[1]);
6311
6312       /* If no string follows, $value gets substituted; otherwise there can
6313       be yes/no strings, as for lookup or if. */
6314
6315       switch(process_yesno(
6316                flags,                           /* were previously skipping */
6317                lookup_value != NULL,            /* success/failure indicator */
6318                save_lookup_value,               /* value to reset for string2 */
6319                &s,                              /* input pointer */
6320                &yield,                          /* output pointer */
6321                US"listextract",                 /* condition type */
6322                &resetok))
6323         {
6324         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6325         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6326         }
6327
6328       /* All done - restore numerical variables. */
6329
6330       restore_expand_strings(save_expand_nmax, save_expand_nstring,
6331         save_expand_nlength);
6332
6333       if (flags & ESI_SKIPPING) continue;
6334       break;
6335       }
6336
6337     case EITEM_LISTQUOTE:
6338       {
6339       uschar * sub[2];
6340       switch(read_subs(sub, 2, 2, &s, flags, TRUE, name, &resetok, NULL))
6341         {
6342         case -1: continue;      /* skipping */
6343         case 1: goto EXPAND_FAILED_CURLY;
6344         case 2:
6345         case 3: goto EXPAND_FAILED;
6346         }
6347       if (*sub[1]) for (uschar sep = *sub[0], c; c = *sub[1]; sub[1]++)
6348         {
6349         if (c == sep) yield = string_catn(yield, sub[1], 1);
6350         yield = string_catn(yield, sub[1], 1);
6351         }
6352       else yield = string_catn(yield, US" ", 1);
6353       break;
6354       }
6355
6356 #ifndef DISABLE_TLS
6357     case EITEM_CERTEXTRACT:
6358       {
6359       uschar * save_lookup_value = lookup_value, * sub[2];
6360       int save_expand_nmax =
6361         save_expand_strings(save_expand_nstring, save_expand_nlength);
6362
6363       /* Read the field argument */
6364       if (Uskip_whitespace(&s) != '{')                                  /*}*/
6365         {
6366         expand_string_message = US"missing '{' for field arg of certextract";
6367         goto EXPAND_FAILED_CURLY;                                       /*}*/
6368         }
6369       sub[0] = expand_string_internal(s+1,
6370                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
6371       if (!sub[0])     goto EXPAND_FAILED;                              /*{{*/
6372       if (*s++ != '}')
6373         {
6374         expand_string_message = US"missing '}' closing field arg of certextract";
6375         goto EXPAND_FAILED_CURLY;
6376         }
6377       /* strip spaces fore & aft */
6378       {
6379       int len;
6380       uschar *p = sub[0];
6381
6382       Uskip_whitespace(&p);
6383       sub[0] = p;
6384
6385       len = Ustrlen(p);
6386       while (len > 0 && isspace(p[len-1])) len--;
6387       p[len] = 0;
6388       }
6389
6390       /* inspect the cert argument */
6391       if (Uskip_whitespace(&s) != '{')                                  /*}*/
6392         {
6393         expand_string_message = US"missing '{' for cert variable arg of certextract";
6394         goto EXPAND_FAILED_CURLY;                                       /*}*/
6395         }
6396       if (*++s != '$')
6397         {
6398         expand_string_message = US"second argument of \"certextract\" must "
6399           "be a certificate variable";
6400         goto EXPAND_FAILED;
6401         }
6402       sub[1] = expand_string_internal(s+1,
6403                 ESI_BRACE_ENDS | flags & ESI_SKIPPING, &s, &resetok, NULL);
6404       if (!sub[1])     goto EXPAND_FAILED;                              /*{{*/
6405       if (*s++ != '}')
6406         {
6407         expand_string_message = US"missing '}' closing cert variable arg of certextract";
6408         goto EXPAND_FAILED_CURLY;
6409         }
6410
6411       if (flags & ESI_SKIPPING)
6412         lookup_value = NULL;
6413       else
6414         {
6415         lookup_value = expand_getcertele(sub[0], sub[1]);
6416         if (*expand_string_message) goto EXPAND_FAILED;
6417         }
6418       switch(process_yesno(
6419                flags,                           /* were previously skipping */
6420                lookup_value != NULL,            /* success/failure indicator */
6421                save_lookup_value,               /* value to reset for string2 */
6422                &s,                              /* input pointer */
6423                &yield,                          /* output pointer */
6424                US"certextract",                 /* condition type */
6425                &resetok))
6426         {
6427         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6428         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6429         }
6430
6431       restore_expand_strings(save_expand_nmax, save_expand_nstring,
6432         save_expand_nlength);
6433       if (flags & ESI_SKIPPING) continue;
6434       break;
6435       }
6436 #endif  /*DISABLE_TLS*/
6437
6438     /* Handle list operations */
6439
6440     case EITEM_FILTER:
6441     case EITEM_MAP:
6442     case EITEM_REDUCE:
6443       {
6444       int sep = 0, save_ptr = gstring_length(yield);
6445       uschar outsep[2] = { '\0', '\0' };
6446       const uschar *list, *expr, *temp;
6447       uschar * save_iterate_item = iterate_item;
6448       uschar * save_lookup_value = lookup_value;
6449
6450       Uskip_whitespace(&s);
6451       if (*s++ != '{')                                                  /*}*/
6452         {
6453         expand_string_message =
6454           string_sprintf("missing '{' for first arg of %s", name);
6455         goto EXPAND_FAILED_CURLY;                                       /*}*/
6456         }
6457
6458       if (!(list = expand_string_internal(s,
6459               ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL)))
6460         goto EXPAND_FAILED;                                             /*{{*/
6461       if (*s++ != '}')
6462         {
6463         expand_string_message =
6464           string_sprintf("missing '}' closing first arg of %s", name);
6465         goto EXPAND_FAILED_CURLY;
6466         }
6467
6468       if (item_type == EITEM_REDUCE)
6469         {
6470         uschar * t;
6471         Uskip_whitespace(&s);
6472         if (*s++ != '{')                                                /*}*/
6473           {
6474           expand_string_message = US"missing '{' for second arg of reduce";
6475           goto EXPAND_FAILED_CURLY;                                     /*}*/
6476           }
6477         t = expand_string_internal(s,
6478               ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
6479         if (!t) goto EXPAND_FAILED;
6480         lookup_value = t;                                               /*{{*/
6481         if (*s++ != '}')
6482           {
6483           expand_string_message = US"missing '}' closing second arg of reduce";
6484           goto EXPAND_FAILED_CURLY;
6485           }
6486         }
6487
6488       Uskip_whitespace(&s);
6489       if (*s++ != '{')                                                  /*}*/
6490         {
6491         expand_string_message =
6492           string_sprintf("missing '{' for last arg of %s", name);       /*}*/
6493         goto EXPAND_FAILED_CURLY;
6494         }
6495
6496       expr = s;
6497
6498       /* For EITEM_FILTER, call eval_condition once, with result discarded (as
6499       if scanning a "false" part). This allows us to find the end of the
6500       condition, because if the list is empty, we won't actually evaluate the
6501       condition for real. For EITEM_MAP and EITEM_REDUCE, do the same, using
6502       the normal internal expansion function. */
6503
6504       if (item_type != EITEM_FILTER)
6505         temp = expand_string_internal(s,
6506           ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | ESI_SKIPPING, &s, &resetok, NULL);
6507       else
6508         if ((temp = eval_condition(expr, &resetok, NULL))) s = temp;
6509
6510       if (!temp)
6511         {
6512         expand_string_message = string_sprintf("%s inside \"%s\" item",
6513           expand_string_message, name);
6514         goto EXPAND_FAILED;
6515         }
6516
6517       Uskip_whitespace(&s);                                             /*{{{*/
6518       if (*s++ != '}')
6519         {
6520         expand_string_message = string_sprintf("missing } at end of condition "
6521           "or expression inside \"%s\"; could be an unquoted } in the content",
6522           name);
6523         goto EXPAND_FAILED;
6524         }
6525
6526       Uskip_whitespace(&s);                                             /*{{*/
6527       if (*s++ != '}')
6528         {
6529         expand_string_message = string_sprintf("missing } at end of \"%s\"",
6530           name);
6531         goto EXPAND_FAILED;
6532         }
6533
6534       /* If we are skipping, we can now just move on to the next item. When
6535       processing for real, we perform the iteration. */
6536
6537       if (flags & ESI_SKIPPING) continue;
6538       while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
6539         {
6540         *outsep = (uschar)sep;      /* Separator as a string */
6541
6542         DEBUG(D_expand) debug_printf_indent("%s: $item = '%s'  $value = '%s'\n",
6543                           name, iterate_item, lookup_value);
6544
6545         if (item_type == EITEM_FILTER)
6546           {
6547           BOOL condresult;
6548           /* the condition could modify $value, as a side-effect */
6549           uschar * save_value = lookup_value;
6550
6551           if (!eval_condition(expr, &resetok, &condresult))
6552             {
6553             iterate_item = save_iterate_item;
6554             lookup_value = save_lookup_value;
6555             expand_string_message = string_sprintf("%s inside \"%s\" condition",
6556               expand_string_message, name);
6557             goto EXPAND_FAILED;
6558             }
6559           lookup_value = save_value;
6560           DEBUG(D_expand) debug_printf_indent("%s: condition is %s\n", name,
6561             condresult? "true":"false");
6562           if (condresult)
6563             temp = iterate_item;    /* TRUE => include this item */
6564           else
6565             continue;               /* FALSE => skip this item */
6566           }
6567
6568         else                    /* EITEM_MAP and EITEM_REDUCE */
6569           {
6570           /* the expansion could modify $value, as a side-effect */
6571           uschar * t = expand_string_internal(expr,
6572             ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, NULL, &resetok, NULL);
6573           if (!(temp = t))
6574             {
6575             iterate_item = save_iterate_item;
6576             expand_string_message = string_sprintf("%s inside \"%s\" item",
6577               expand_string_message, name);
6578             goto EXPAND_FAILED;
6579             }
6580           if (item_type == EITEM_REDUCE)
6581             {
6582             lookup_value = t;         /* Update the value of $value */
6583             continue;                 /* and continue the iteration */
6584             }
6585           }
6586
6587         /* We reach here for FILTER if the condition is true, always for MAP,
6588         and never for REDUCE. The value in "temp" is to be added to the output
6589         list that is being created, ensuring that any occurrences of the
6590         separator character are doubled. Unless we are dealing with the first
6591         item of the output list, add in a space if the new item begins with the
6592         separator character, or is an empty string. */
6593
6594 /*XXX is there not a standard support function for this, appending to a list? */
6595 /* yes, string_append_listele(), but it depends on lack of text before the list */
6596
6597         if (  yield && yield->ptr != save_ptr
6598            && (temp[0] == *outsep || temp[0] == 0))
6599           yield = string_catn(yield, US" ", 1);
6600
6601         /* Add the string in "temp" to the output list that we are building,
6602         This is done in chunks by searching for the separator character. */
6603
6604         for (;;)
6605           {
6606           size_t seglen = Ustrcspn(temp, outsep);
6607
6608           yield = string_catn(yield, temp, seglen + 1);
6609
6610           /* If we got to the end of the string we output one character
6611           too many; backup and end the loop. Otherwise arrange to double the
6612           separator. */
6613
6614           if (!temp[seglen]) { yield->ptr--; break; }
6615           yield = string_catn(yield, outsep, 1);
6616           temp += seglen + 1;
6617           }
6618
6619         /* Output a separator after the string: we will remove the redundant
6620         final one at the end. */
6621
6622         yield = string_catn(yield, outsep, 1);
6623         }   /* End of iteration over the list loop */
6624
6625       /* REDUCE has generated no output above: output the final value of
6626       $value. */
6627
6628       if (item_type == EITEM_REDUCE)
6629         {
6630         yield = string_cat(yield, lookup_value);
6631         lookup_value = save_lookup_value;  /* Restore $value */
6632         }
6633
6634       /* FILTER and MAP generate lists: if they have generated anything, remove
6635       the redundant final separator. Even though an empty item at the end of a
6636       list does not count, this is tidier. */
6637
6638       else if (yield && yield->ptr != save_ptr) yield->ptr--;
6639
6640       /* Restore preserved $item */
6641
6642       iterate_item = save_iterate_item;
6643       if (flags & ESI_SKIPPING) continue;
6644       break;
6645       }
6646
6647     case EITEM_SORT:
6648       {
6649       int sep = 0, cond_type;
6650       const uschar * srclist, * cmp, * xtract;
6651       uschar * opname, * srcitem;
6652       const uschar * dstlist = NULL, * dstkeylist = NULL;
6653       uschar * tmp, * save_iterate_item = iterate_item;
6654
6655       Uskip_whitespace(&s);
6656       if (*s++ != '{')                                                  /*}*/
6657         {
6658         expand_string_message = US"missing '{' for list arg of sort";
6659         goto EXPAND_FAILED_CURLY;                                       /*}*/
6660         }
6661
6662       srclist = expand_string_internal(s,
6663               ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
6664       if (!srclist) goto EXPAND_FAILED;                                 /*{{*/
6665       if (*s++ != '}')
6666         {
6667         expand_string_message = US"missing '}' closing list arg of sort";
6668         goto EXPAND_FAILED_CURLY;
6669         }
6670
6671       Uskip_whitespace(&s);
6672       if (*s++ != '{')                                                  /*}*/
6673         {
6674         expand_string_message = US"missing '{' for comparator arg of sort";
6675         goto EXPAND_FAILED_CURLY;                                       /*}*/
6676         }
6677
6678       cmp = expand_string_internal(s,
6679               ESI_BRACE_ENDS | flags & ESI_SKIPPING, &s, &resetok, NULL);
6680       if (!cmp) goto EXPAND_FAILED;                                     /*{{*/
6681       if (*s++ != '}')
6682         {
6683         expand_string_message = US"missing '}' closing comparator arg of sort";
6684         goto EXPAND_FAILED_CURLY;
6685         }
6686
6687       if ((cond_type = identify_operator(&cmp, &opname)) == -1)
6688         {
6689         if (!expand_string_message)
6690           expand_string_message = string_sprintf("unknown condition \"%s\"", s);
6691         goto EXPAND_FAILED;
6692         }
6693       switch(cond_type)
6694         {
6695         case ECOND_NUM_L: case ECOND_NUM_LE:
6696         case ECOND_NUM_G: case ECOND_NUM_GE:
6697         case ECOND_STR_GE: case ECOND_STR_GEI: case ECOND_STR_GT: case ECOND_STR_GTI:
6698         case ECOND_STR_LE: case ECOND_STR_LEI: case ECOND_STR_LT: case ECOND_STR_LTI:
6699           break;
6700
6701         default:
6702           expand_string_message = US"comparator not handled for sort";
6703           goto EXPAND_FAILED;
6704         }
6705
6706       Uskip_whitespace(&s);
6707       if (*s++ != '{')                                                  /*}*/
6708         {
6709         expand_string_message = US"missing '{' for extractor arg of sort";
6710         goto EXPAND_FAILED_CURLY;                                       /*}*/
6711         }
6712
6713       xtract = s;
6714       if (!(tmp = expand_string_internal(s,
6715         ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | ESI_SKIPPING, &s, &resetok, NULL)))
6716         goto EXPAND_FAILED;
6717       xtract = string_copyn(xtract, s - xtract);
6718                                                                         /*{{*/
6719       if (*s++ != '}')
6720         {
6721         expand_string_message = US"missing '}' closing extractor arg of sort";
6722         goto EXPAND_FAILED_CURLY;
6723         }
6724                                                                         /*{{*/
6725       if (*s++ != '}')
6726         {
6727         expand_string_message = US"missing } at end of \"sort\"";
6728         goto EXPAND_FAILED;
6729         }
6730
6731       if (flags & ESI_SKIPPING) continue;
6732
6733       while ((srcitem = string_nextinlist(&srclist, &sep, NULL, 0)))
6734         {
6735         uschar * srcfield, * dstitem;
6736         gstring * newlist = NULL, * newkeylist = NULL;
6737
6738         DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", name, srcitem);
6739
6740         /* extract field for comparisons */
6741         iterate_item = srcitem;
6742         if (  !(srcfield = expand_string_internal(xtract,
6743                                   ESI_HONOR_DOLLAR, NULL, &resetok, NULL))
6744            || !*srcfield)
6745           {
6746           expand_string_message = string_sprintf(
6747               "field-extract in sort: \"%s\"", xtract);
6748           goto EXPAND_FAILED;
6749           }
6750
6751         /* Insertion sort */
6752
6753         /* copy output list until new-item < list-item */
6754         while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
6755           {
6756           uschar * dstfield;
6757
6758           /* field for comparison */
6759           if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
6760             goto SORT_MISMATCH;
6761
6762           /* String-comparator names start with a letter; numeric names do not */
6763
6764           if (sortsbefore(cond_type, isalpha(opname[0]),
6765               srcfield, dstfield))
6766             {
6767             /* New-item sorts before this dst-item.  Append new-item,
6768             then dst-item, then remainder of dst list. */
6769
6770             newlist = string_append_listele(newlist, sep, srcitem);
6771             newkeylist = string_append_listele(newkeylist, sep, srcfield);
6772             srcitem = NULL;
6773
6774             newlist = string_append_listele(newlist, sep, dstitem);
6775             newkeylist = string_append_listele(newkeylist, sep, dstfield);
6776
6777 /*XXX why field-at-a-time copy?  Why not just dup the rest of the list? */
6778             while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
6779               {
6780               if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
6781                 goto SORT_MISMATCH;
6782               newlist = string_append_listele(newlist, sep, dstitem);
6783               newkeylist = string_append_listele(newkeylist, sep, dstfield);
6784               }
6785
6786             break;
6787             }
6788
6789           newlist = string_append_listele(newlist, sep, dstitem);
6790           newkeylist = string_append_listele(newkeylist, sep, dstfield);
6791           }
6792
6793         /* If we ran out of dstlist without consuming srcitem, append it */
6794         if (srcitem)
6795           {
6796           newlist = string_append_listele(newlist, sep, srcitem);
6797           newkeylist = string_append_listele(newkeylist, sep, srcfield);
6798           }
6799
6800         dstlist = newlist->s;
6801         dstkeylist = newkeylist->s;
6802
6803         DEBUG(D_expand) debug_printf_indent("%s: dstlist = \"%s\"\n", name, dstlist);
6804         DEBUG(D_expand) debug_printf_indent("%s: dstkeylist = \"%s\"\n", name, dstkeylist);
6805         }
6806
6807       if (dstlist)
6808         yield = string_cat(yield, dstlist);
6809
6810       /* Restore preserved $item */
6811       iterate_item = save_iterate_item;
6812       break;
6813
6814       SORT_MISMATCH:
6815         expand_string_message = US"Internal error in sort (list mismatch)";
6816         goto EXPAND_FAILED;
6817       }
6818
6819
6820     /* If ${dlfunc } support is configured, handle calling dynamically-loaded
6821     functions, unless locked out at this time. Syntax is ${dlfunc{file}{func}}
6822     or ${dlfunc{file}{func}{arg}} or ${dlfunc{file}{func}{arg1}{arg2}} or up to
6823     a maximum of EXPAND_DLFUNC_MAX_ARGS arguments (defined below). */
6824
6825     #define EXPAND_DLFUNC_MAX_ARGS 8
6826
6827     case EITEM_DLFUNC:
6828 #ifndef EXPAND_DLFUNC
6829       expand_string_message = US"\"${dlfunc\" encountered, but this facility "  /*}*/
6830         "is not included in this binary";
6831       goto EXPAND_FAILED;
6832
6833 #else   /* EXPAND_DLFUNC */
6834       {
6835       tree_node * t;
6836       exim_dlfunc_t * func;
6837       uschar * result;
6838       int status, argc;
6839       uschar * argv[EXPAND_DLFUNC_MAX_ARGS + 3];
6840
6841       if (expand_forbid & RDO_DLFUNC)
6842         {
6843         expand_string_message =
6844           US"dynamically-loaded functions are not permitted";
6845         goto EXPAND_FAILED;
6846         }
6847
6848       switch(read_subs(argv, EXPAND_DLFUNC_MAX_ARGS + 2, 2, &s, flags,
6849            TRUE, name, &resetok, NULL))
6850         {
6851         case -1: continue;      /* skipping */
6852         case 1: goto EXPAND_FAILED_CURLY;
6853         case 2:
6854         case 3: goto EXPAND_FAILED;
6855         }
6856
6857       /* Look up the dynamically loaded object handle in the tree. If it isn't
6858       found, dlopen() the file and put the handle in the tree for next time. */
6859
6860       if (!(t = tree_search(dlobj_anchor, argv[0])))
6861         {
6862         void * handle = dlopen(CS argv[0], RTLD_LAZY);
6863         if (!handle)
6864           {
6865           expand_string_message = string_sprintf("dlopen \"%s\" failed: %s",
6866             argv[0], dlerror());
6867           log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
6868           goto EXPAND_FAILED;
6869           }
6870         t = store_get_perm(sizeof(tree_node) + Ustrlen(argv[0]), argv[0]);
6871         Ustrcpy(t->name, argv[0]);
6872         t->data.ptr = handle;
6873         (void)tree_insertnode(&dlobj_anchor, t);
6874         }
6875
6876       /* Having obtained the dynamically loaded object handle, look up the
6877       function pointer. */
6878
6879       if (!(func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1])))
6880         {
6881         expand_string_message = string_sprintf("dlsym \"%s\" in \"%s\" failed: "
6882           "%s", argv[1], argv[0], dlerror());
6883         log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
6884         goto EXPAND_FAILED;
6885         }
6886
6887       /* Call the function and work out what to do with the result. If it
6888       returns OK, we have a replacement string; if it returns DEFER then
6889       expansion has failed in a non-forced manner; if it returns FAIL then
6890       failure was forced; if it returns ERROR or any other value there's a
6891       problem, so panic slightly. In any case, assume that the function has
6892       side-effects on the store that must be preserved. */
6893
6894       resetok = FALSE;
6895       result = NULL;
6896       for (argc = 0; argv[argc]; argc++) ;
6897
6898       if ((status = func(&result, argc - 2, &argv[2])) != OK)
6899         {
6900         expand_string_message = result ? result : US"(no message)";
6901         if (status == FAIL_FORCED)
6902           f.expand_string_forcedfail = TRUE;
6903         else if (status != FAIL)
6904           log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
6905               argv[0], argv[1], status, expand_string_message);
6906         goto EXPAND_FAILED;
6907         }
6908
6909       if (result) yield = string_cat(yield, result);
6910       break;
6911       }
6912 #endif /* EXPAND_DLFUNC */
6913
6914     case EITEM_ENV:     /* ${env {name} {val_if_found} {val_if_unfound}} */
6915       {
6916       uschar * key;
6917       uschar *save_lookup_value = lookup_value;
6918
6919       if (Uskip_whitespace(&s) != '{')                                  /*}*/
6920         goto EXPAND_FAILED;
6921
6922       key = expand_string_internal(s+1,
6923               ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
6924       if (!key) goto EXPAND_FAILED;                                     /*{{*/
6925       if (*s++ != '}')
6926         {
6927         expand_string_message = US"missing '}' for name arg of env";
6928         goto EXPAND_FAILED_CURLY;
6929         }
6930
6931       lookup_value = US getenv(CS key);
6932
6933       switch(process_yesno(
6934                flags,                           /* were previously skipping */
6935                lookup_value != NULL,            /* success/failure indicator */
6936                save_lookup_value,               /* value to reset for string2 */
6937                &s,                              /* input pointer */
6938                &yield,                          /* output pointer */
6939                US"env",                         /* condition type */
6940                &resetok))
6941         {
6942         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6943         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6944         }
6945       if (flags & ESI_SKIPPING) continue;
6946       break;
6947       }
6948
6949 #ifdef SUPPORT_SRS
6950     case EITEM_SRS_ENCODE:
6951       /* ${srs_encode {secret} {return_path} {orig_domain}} */
6952       {
6953       uschar * sub[3];
6954       uschar cksum[4];
6955       gstring * g = NULL;
6956       BOOL quoted = FALSE;
6957
6958       switch (read_subs(sub, 3, 3, CUSS &s, flags, TRUE, name, &resetok, NULL))
6959         {
6960         case -1: continue;      /* skipping */
6961         case 1: goto EXPAND_FAILED_CURLY;
6962         case 2:
6963         case 3: goto EXPAND_FAILED;
6964         }
6965
6966       if (sub[1] && *(sub[1]))
6967         {
6968         g = string_catn(g, US"SRS0=", 5);
6969
6970         /* ${l_4:${hmac{md5}{SRS_SECRET}{${lc:$return_path}}}}= */
6971         hmac_md5(sub[0], string_copylc(sub[1]), cksum, sizeof(cksum));
6972         g = string_catn(g, cksum, sizeof(cksum));
6973         g = string_catn(g, US"=", 1);
6974
6975         /* ${base32:${eval:$tod_epoch/86400&0x3ff}}= */
6976           {
6977           struct timeval now;
6978           unsigned long i;
6979           gstring * h = NULL;
6980
6981           gettimeofday(&now, NULL);
6982           for (unsigned long i = (now.tv_sec / 86400) & 0x3ff; i; i >>= 5)
6983             h = string_catn(h, &base32_chars[i & 0x1f], 1);
6984           if (h) while (h->ptr > 0)
6985             g = string_catn(g, &h->s[--h->ptr], 1);
6986           }
6987         g = string_catn(g, US"=", 1);
6988
6989         /* ${domain:$return_path}=${local_part:$return_path} */
6990           {
6991           int start, end, domain;
6992           uschar * t = parse_extract_address(sub[1], &expand_string_message,
6993                                             &start, &end, &domain, FALSE);
6994           uschar * s;
6995
6996           if (!t)
6997             goto EXPAND_FAILED;
6998
6999           if (domain > 0) g = string_cat(g, t + domain);
7000           g = string_catn(g, US"=", 1);
7001
7002           s = domain > 0 ? string_copyn(t, domain - 1) : t;
7003           if ((quoted = Ustrchr(s, '"') != NULL))
7004             {
7005             gstring * h = NULL;
7006             DEBUG(D_expand) debug_printf_indent("auto-quoting local part\n");
7007             while (*s)          /* de-quote */
7008               {
7009               while (*s && *s != '"') h = string_catn(h, s++, 1);
7010               if (*s) s++;
7011               while (*s && *s != '"') h = string_catn(h, s++, 1);
7012               if (*s) s++;
7013               }
7014             gstring_release_unused(h);
7015             s = string_from_gstring(h);
7016             }
7017           g = string_cat(g, s);
7018           }
7019
7020         /* Assume that if the original local_part had quotes
7021         it was for good reason */
7022
7023         if (quoted) yield = string_catn(yield, US"\"", 1);
7024         yield = string_catn(yield, g->s, g->ptr);
7025         if (quoted) yield = string_catn(yield, US"\"", 1);
7026
7027         /* @$original_domain */
7028         yield = string_catn(yield, US"@", 1);
7029         yield = string_cat(yield, sub[2]);
7030         }
7031       else
7032         DEBUG(D_expand) debug_printf_indent("null return_path for srs-encode\n");
7033
7034       break;
7035       }
7036 #endif /*SUPPORT_SRS*/
7037
7038     default:
7039       goto NOT_ITEM;
7040     }   /* EITEM_* switch */
7041     /*NOTREACHED*/
7042
7043   DEBUG(D_expand)
7044     if (yield && (start > 0 || *s))     /* only if not the sole expansion of the line */
7045       debug_expansion_interim(US"item-res",
7046                               yield->s + start, yield->ptr - start, !!(flags & ESI_SKIPPING));
7047   continue;
7048
7049 NOT_ITEM: ;
7050   }
7051
7052   /* Control reaches here if the name is not recognized as one of the more
7053   complicated expansion items. Check for the "operator" syntax (name terminated
7054   by a colon). Some of the operators have arguments, separated by _ from the
7055   name. */
7056
7057   if (*s == ':')
7058     {
7059     int c;
7060     uschar * arg = NULL, * sub;
7061 #ifndef DISABLE_TLS
7062     var_entry * vp = NULL;
7063 #endif
7064
7065     /* Owing to an historical mis-design, an underscore may be part of the
7066     operator name, or it may introduce arguments.  We therefore first scan the
7067     table of names that contain underscores. If there is no match, we cut off
7068     the arguments and then scan the main table. */
7069
7070     if ((c = chop_match(name, op_table_underscore,
7071                         nelem(op_table_underscore))) < 0)
7072       {
7073       if ((arg = Ustrchr(name, '_')))
7074         *arg = 0;
7075       if ((c = chop_match(name, op_table_main, nelem(op_table_main))) >= 0)
7076         c += nelem(op_table_underscore);
7077       if (arg) *arg++ = '_';            /* Put back for error messages */
7078       }
7079
7080     /* Deal specially with operators that might take a certificate variable
7081     as we do not want to do the usual expansion. For most, expand the string.*/
7082     switch(c)
7083       {
7084 #ifndef DISABLE_TLS
7085       case EOP_MD5:
7086       case EOP_SHA1:
7087       case EOP_SHA256:
7088       case EOP_BASE64:
7089         if (s[1] == '$')
7090           {
7091           const uschar * s1 = s;
7092           sub = expand_string_internal(s+2,
7093               ESI_BRACE_ENDS | flags & ESI_SKIPPING, &s1, &resetok, NULL);
7094           if (!sub)       goto EXPAND_FAILED;           /*{*/
7095           if (*s1 != '}')
7096             {                                           /*{*/
7097             expand_string_message =
7098               string_sprintf("missing '}' closing cert arg of %s", name);
7099             goto EXPAND_FAILED_CURLY;
7100             }
7101           if ((vp = find_var_ent(sub)) && vp->type == vtype_cert)
7102             {
7103             s = s1+1;
7104             break;
7105             }
7106           vp = NULL;
7107           }
7108         /*FALLTHROUGH*/
7109 #endif
7110       default:
7111         sub = expand_string_internal(s+1,
7112                 ESI_BRACE_ENDS | ESI_HONOR_DOLLAR | flags, &s, &resetok, NULL);
7113         if (!sub) goto EXPAND_FAILED;
7114         s++;
7115         break;
7116       }
7117
7118     /* If we are skipping, we don't need to perform the operation at all.
7119     This matters for operations like "mask", because the data may not be
7120     in the correct format when skipping. For example, the expression may test
7121     for the existence of $sender_host_address before trying to mask it. For
7122     other operations, doing them may not fail, but it is a waste of time. */
7123
7124     if (flags & ESI_SKIPPING && c >= 0) continue;
7125
7126     /* Otherwise, switch on the operator type.  After handling go back
7127     to the main loop top. */
7128
7129      {
7130      int start = yield->ptr;
7131      switch(c)
7132       {
7133       case EOP_BASE32:
7134         {
7135         uschar *t;
7136         unsigned long int n = Ustrtoul(sub, &t, 10);
7137         gstring * g = NULL;
7138
7139         if (*t != 0)
7140           {
7141           expand_string_message = string_sprintf("argument for base32 "
7142             "operator is \"%s\", which is not a decimal number", sub);
7143           goto EXPAND_FAILED;
7144           }
7145         for ( ; n; n >>= 5)
7146           g = string_catn(g, &base32_chars[n & 0x1f], 1);
7147
7148         if (g) while (g->ptr > 0) yield = string_catn(yield, &g->s[--g->ptr], 1);
7149         break;
7150         }
7151
7152       case EOP_BASE32D:
7153         {
7154         uschar *tt = sub;
7155         unsigned long int n = 0;
7156         while (*tt)
7157           {
7158           uschar * t = Ustrchr(base32_chars, *tt++);
7159           if (!t)
7160             {
7161             expand_string_message = string_sprintf("argument for base32d "
7162               "operator is \"%s\", which is not a base 32 number", sub);
7163             goto EXPAND_FAILED;
7164             }
7165           n = n * 32 + (t - base32_chars);
7166           }
7167         yield = string_fmt_append(yield, "%ld", n);
7168         break;
7169         }
7170
7171       case EOP_BASE62:
7172         {
7173         uschar *t;
7174         unsigned long int n = Ustrtoul(sub, &t, 10);
7175         if (*t != 0)
7176           {
7177           expand_string_message = string_sprintf("argument for base62 "
7178             "operator is \"%s\", which is not a decimal number", sub);
7179           goto EXPAND_FAILED;
7180           }
7181         yield = string_cat(yield, string_base62(n));
7182         break;
7183         }
7184
7185       /* Note that for Darwin and Cygwin, BASE_62 actually has the value 36 */
7186
7187       case EOP_BASE62D:
7188         {
7189         uschar *tt = sub;
7190         unsigned long int n = 0;
7191         while (*tt != 0)
7192           {
7193           uschar *t = Ustrchr(base62_chars, *tt++);
7194           if (!t)
7195             {
7196             expand_string_message = string_sprintf("argument for base62d "
7197               "operator is \"%s\", which is not a base %d number", sub,
7198               BASE_62);
7199             goto EXPAND_FAILED;
7200             }
7201           n = n * BASE_62 + (t - base62_chars);
7202           }
7203         yield = string_fmt_append(yield, "%ld", n);
7204         break;
7205         }
7206
7207       case EOP_EXPAND:
7208         {
7209         uschar *expanded = expand_string_internal(sub,
7210                 ESI_HONOR_DOLLAR | flags & ESI_SKIPPING, NULL, &resetok, NULL);
7211         if (!expanded)
7212           {
7213           expand_string_message =
7214             string_sprintf("internal expansion of \"%s\" failed: %s", sub,
7215               expand_string_message);
7216           goto EXPAND_FAILED;
7217           }
7218         yield = string_cat(yield, expanded);
7219         break;
7220         }
7221
7222       case EOP_LC:
7223         {
7224         int count = 0;
7225         uschar *t = sub - 1;
7226         while (*(++t) != 0) { *t = tolower(*t); count++; }
7227         yield = string_catn(yield, sub, count);
7228         break;
7229         }
7230
7231       case EOP_UC:
7232         {
7233         int count = 0;
7234         uschar *t = sub - 1;
7235         while (*(++t) != 0) { *t = toupper(*t); count++; }
7236         yield = string_catn(yield, sub, count);
7237         break;
7238         }
7239
7240       case EOP_MD5:
7241 #ifndef DISABLE_TLS
7242         if (vp && *(void **)vp->value)
7243           {
7244           uschar * cp = tls_cert_fprt_md5(*(void **)vp->value);
7245           yield = string_cat(yield, cp);
7246           }
7247         else
7248 #endif
7249           {
7250           md5 base;
7251           uschar digest[16];
7252           md5_start(&base);
7253           md5_end(&base, sub, Ustrlen(sub), digest);
7254           for (int j = 0; j < 16; j++)
7255             yield = string_fmt_append(yield, "%02x", digest[j]);
7256           }
7257         break;
7258
7259       case EOP_SHA1:
7260 #ifndef DISABLE_TLS
7261         if (vp && *(void **)vp->value)
7262           {
7263           uschar * cp = tls_cert_fprt_sha1(*(void **)vp->value);
7264           yield = string_cat(yield, cp);
7265           }
7266         else
7267 #endif
7268           {
7269           hctx h;
7270           uschar digest[20];
7271           sha1_start(&h);
7272           sha1_end(&h, sub, Ustrlen(sub), digest);
7273           for (int j = 0; j < 20; j++)
7274             yield = string_fmt_append(yield, "%02X", digest[j]);
7275           }
7276         break;
7277
7278       case EOP_SHA2:
7279       case EOP_SHA256:
7280 #ifdef EXIM_HAVE_SHA2
7281         if (vp && *(void **)vp->value)
7282           if (c == EOP_SHA256)
7283             yield = string_cat(yield, tls_cert_fprt_sha256(*(void **)vp->value));
7284           else
7285             expand_string_message = US"sha2_N not supported with certificates";
7286         else
7287           {
7288           hctx h;
7289           blob b;
7290           hashmethod m = !arg ? HASH_SHA2_256
7291             : Ustrcmp(arg, "256") == 0 ? HASH_SHA2_256
7292             : Ustrcmp(arg, "384") == 0 ? HASH_SHA2_384
7293             : Ustrcmp(arg, "512") == 0 ? HASH_SHA2_512
7294             : HASH_BADTYPE;
7295
7296           if (m == HASH_BADTYPE || !exim_sha_init(&h, m))
7297             {
7298             expand_string_message = US"unrecognised sha2 variant";
7299             goto EXPAND_FAILED;
7300             }
7301
7302           exim_sha_update_string(&h, sub);
7303           exim_sha_finish(&h, &b);
7304           while (b.len-- > 0)
7305             yield = string_fmt_append(yield, "%02X", *b.data++);
7306           }
7307 #else
7308           expand_string_message = US"sha256 only supported with TLS";
7309 #endif
7310         break;
7311
7312       case EOP_SHA3:
7313 #ifdef EXIM_HAVE_SHA3
7314         {
7315         hctx h;
7316         blob b;
7317         hashmethod m = !arg ? HASH_SHA3_256
7318           : Ustrcmp(arg, "224") == 0 ? HASH_SHA3_224
7319           : Ustrcmp(arg, "256") == 0 ? HASH_SHA3_256
7320           : Ustrcmp(arg, "384") == 0 ? HASH_SHA3_384
7321           : Ustrcmp(arg, "512") == 0 ? HASH_SHA3_512
7322           : HASH_BADTYPE;
7323
7324         if (m == HASH_BADTYPE || !exim_sha_init(&h, m))
7325           {
7326           expand_string_message = US"unrecognised sha3 variant";
7327           goto EXPAND_FAILED;
7328           }
7329
7330         exim_sha_update_string(&h, sub);
7331         exim_sha_finish(&h, &b);
7332         while (b.len-- > 0)
7333           yield = string_fmt_append(yield, "%02X", *b.data++);
7334         }
7335         break;
7336 #else
7337         expand_string_message = US"sha3 only supported with GnuTLS 3.5.0 + or OpenSSL 1.1.1 +";
7338         goto EXPAND_FAILED;
7339 #endif
7340
7341       /* Convert hex encoding to base64 encoding */
7342
7343       case EOP_HEX2B64:
7344         {
7345         int c = 0;
7346         int b = -1;
7347         uschar *in = sub;
7348         uschar *out = sub;
7349         uschar *enc;
7350
7351         for (enc = sub; *enc; enc++)
7352           {
7353           if (!isxdigit(*enc))
7354             {
7355             expand_string_message = string_sprintf("\"%s\" is not a hex "
7356               "string", sub);
7357             goto EXPAND_FAILED;
7358             }
7359           c++;
7360           }
7361
7362         if ((c & 1) != 0)
7363           {
7364           expand_string_message = string_sprintf("\"%s\" contains an odd "
7365             "number of characters", sub);
7366           goto EXPAND_FAILED;
7367           }
7368
7369         while ((c = *in++) != 0)
7370           {
7371           if (isdigit(c)) c -= '0';
7372           else c = toupper(c) - 'A' + 10;
7373           if (b == -1)
7374             b = c << 4;
7375           else
7376             {
7377             *out++ = b | c;
7378             b = -1;
7379             }
7380           }
7381
7382         enc = b64encode(CUS sub, out - sub);
7383         yield = string_cat(yield, enc);
7384         break;
7385         }
7386
7387       /* Convert octets outside 0x21..0x7E to \xXX form */
7388
7389       case EOP_HEXQUOTE:
7390         {
7391         uschar *t = sub - 1;
7392         while (*(++t) != 0)
7393           {
7394           if (*t < 0x21 || 0x7E < *t)
7395             yield = string_fmt_append(yield, "\\x%02x", *t);
7396           else
7397             yield = string_catn(yield, t, 1);
7398           }
7399         break;
7400         }
7401
7402       /* count the number of list elements */
7403
7404       case EOP_LISTCOUNT:
7405         {
7406         int cnt = 0, sep = 0;
7407         uschar * buf = store_get(2, sub);
7408
7409         while (string_nextinlist(CUSS &sub, &sep, buf, 1)) cnt++;
7410         yield = string_fmt_append(yield, "%d", cnt);
7411         break;
7412         }
7413
7414       /* expand a named list given the name */
7415       /* handles nested named lists; requotes as colon-sep list */
7416
7417       case EOP_LISTNAMED:
7418         expand_string_message = NULL;
7419         yield = expand_listnamed(yield, sub, arg);
7420         if (expand_string_message)
7421           goto EXPAND_FAILED;
7422         break;
7423
7424       /* quote a list-item for the given list-separator */
7425
7426       /* mask applies a mask to an IP address; for example the result of
7427       ${mask:131.111.10.206/28} is 131.111.10.192/28. */
7428
7429       case EOP_MASK:
7430         {
7431         int count;
7432         uschar *endptr;
7433         int binary[4];
7434         int type, mask, maskoffset;
7435         BOOL normalised;
7436         uschar buffer[64];
7437
7438         if ((type = string_is_ip_address(sub, &maskoffset)) == 0)
7439           {
7440           expand_string_message = string_sprintf("\"%s\" is not an IP address",
7441            sub);
7442           goto EXPAND_FAILED;
7443           }
7444
7445         if (maskoffset == 0)
7446           {
7447           expand_string_message = string_sprintf("missing mask value in \"%s\"",
7448             sub);
7449           goto EXPAND_FAILED;
7450           }
7451
7452         mask = Ustrtol(sub + maskoffset + 1, &endptr, 10);
7453
7454         if (*endptr || mask < 0 || mask > (type == 4 ? 32 : 128))
7455           {
7456           expand_string_message = string_sprintf("mask value too big in \"%s\"",
7457             sub);
7458           goto EXPAND_FAILED;
7459           }
7460
7461         /* If an optional 'n' was given, ipv6 gets normalised output:
7462         colons rather than dots, and zero-compressed. */
7463
7464         normalised = arg && *arg == 'n';
7465
7466         /* Convert the address to binary integer(s) and apply the mask */
7467
7468         sub[maskoffset] = 0;
7469         count = host_aton(sub, binary);
7470         host_mask(count, binary, mask);
7471
7472         /* Convert to masked textual format and add to output. */
7473
7474         if (type == 4 || !normalised)
7475           yield = string_catn(yield, buffer,
7476             host_nmtoa(count, binary, mask, buffer, '.'));
7477         else
7478           {
7479           ipv6_nmtoa(binary, buffer);
7480           yield = string_fmt_append(yield, "%s/%d", buffer, mask);
7481           }
7482         break;
7483         }
7484
7485       case EOP_IPV6NORM:
7486       case EOP_IPV6DENORM:
7487         {
7488         int type = string_is_ip_address(sub, NULL);
7489         int binary[4];
7490         uschar buffer[44];
7491
7492         switch (type)
7493           {
7494           case 6:
7495             (void) host_aton(sub, binary);
7496             break;
7497
7498           case 4:       /* convert to IPv4-mapped IPv6 */
7499             binary[0] = binary[1] = 0;
7500             binary[2] = 0x0000ffff;
7501             (void) host_aton(sub, binary+3);
7502             break;
7503
7504           case 0:
7505             expand_string_message =
7506               string_sprintf("\"%s\" is not an IP address", sub);
7507             goto EXPAND_FAILED;
7508           }
7509
7510         yield = string_catn(yield, buffer, c == EOP_IPV6NORM
7511                     ? ipv6_nmtoa(binary, buffer)
7512                     : host_nmtoa(4, binary, -1, buffer, ':')
7513                   );
7514         break;
7515         }
7516
7517       case EOP_ADDRESS:
7518       case EOP_LOCAL_PART:
7519       case EOP_DOMAIN:
7520         {
7521         uschar * error;
7522         int start, end, domain;
7523         uschar * t = parse_extract_address(sub, &error, &start, &end, &domain,
7524           FALSE);
7525         if (t)
7526           if (c != EOP_DOMAIN)
7527             yield = c == EOP_LOCAL_PART && domain > 0
7528               ? string_catn(yield, t, domain - 1)
7529               : string_cat(yield, t);
7530           else if (domain > 0)
7531             yield = string_cat(yield, t + domain);
7532         break;
7533         }
7534
7535       case EOP_ADDRESSES:
7536         {
7537         uschar outsep[2] = { ':', '\0' };
7538         uschar *address, *error;
7539         int save_ptr = gstring_length(yield);
7540         int start, end, domain;  /* Not really used */
7541
7542         if (Uskip_whitespace(&sub) == '>')
7543           if (*outsep = *++sub) ++sub;
7544           else
7545             {
7546             expand_string_message = string_sprintf("output separator "
7547               "missing in expanding ${addresses:%s}", --sub);
7548             goto EXPAND_FAILED;
7549             }
7550         f.parse_allow_group = TRUE;
7551
7552         for (;;)
7553           {
7554           uschar * p = parse_find_address_end(sub, FALSE);
7555           uschar saveend = *p;
7556           *p = '\0';
7557           address = parse_extract_address(sub, &error, &start, &end, &domain,
7558             FALSE);
7559           *p = saveend;
7560
7561           /* Add the address to the output list that we are building. This is
7562           done in chunks by searching for the separator character. At the
7563           start, unless we are dealing with the first address of the output
7564           list, add in a space if the new address begins with the separator
7565           character, or is an empty string. */
7566
7567           if (address)
7568             {
7569             if (yield && yield->ptr != save_ptr && address[0] == *outsep)
7570               yield = string_catn(yield, US" ", 1);
7571
7572             for (;;)
7573               {
7574               size_t seglen = Ustrcspn(address, outsep);
7575               yield = string_catn(yield, address, seglen + 1);
7576
7577               /* If we got to the end of the string we output one character
7578               too many. */
7579
7580               if (address[seglen] == '\0') { yield->ptr--; break; }
7581               yield = string_catn(yield, outsep, 1);
7582               address += seglen + 1;
7583               }
7584
7585             /* Output a separator after the string: we will remove the
7586             redundant final one at the end. */
7587
7588             yield = string_catn(yield, outsep, 1);
7589             }
7590
7591           if (saveend == '\0') break;
7592           sub = p + 1;
7593           }
7594
7595         /* If we have generated anything, remove the redundant final
7596         separator. */
7597
7598         if (yield && yield->ptr != save_ptr) yield->ptr--;
7599         f.parse_allow_group = FALSE;
7600         break;
7601         }
7602
7603
7604       /* quote puts a string in quotes if it is empty or contains anything
7605       other than alphamerics, underscore, dot, or hyphen.
7606
7607       quote_local_part puts a string in quotes if RFC 2821/2822 requires it to
7608       be quoted in order to be a valid local part.
7609
7610       In both cases, newlines and carriage returns are converted into \n and \r
7611       respectively */
7612
7613       case EOP_QUOTE:
7614       case EOP_QUOTE_LOCAL_PART:
7615         if (!arg)
7616           {
7617           BOOL needs_quote = (!*sub);      /* TRUE for empty string */
7618           uschar *t = sub - 1;
7619
7620           if (c == EOP_QUOTE)
7621             while (!needs_quote && *++t)
7622               needs_quote = !isalnum(*t) && !strchr("_-.", *t);
7623
7624           else  /* EOP_QUOTE_LOCAL_PART */
7625             while (!needs_quote && *++t)
7626               needs_quote = !isalnum(*t)
7627                 && strchr("!#$%&'*+-/=?^_`{|}~", *t) == NULL
7628                 && (*t != '.' || t == sub || !t[1]);
7629
7630           if (needs_quote)
7631             {
7632             yield = string_catn(yield, US"\"", 1);
7633             t = sub - 1;
7634             while (*++t)
7635               if (*t == '\n')
7636                 yield = string_catn(yield, US"\\n", 2);
7637               else if (*t == '\r')
7638                 yield = string_catn(yield, US"\\r", 2);
7639               else
7640                 {
7641                 if (*t == '\\' || *t == '"')
7642                   yield = string_catn(yield, US"\\", 1);
7643                 yield = string_catn(yield, t, 1);
7644                 }
7645             yield = string_catn(yield, US"\"", 1);
7646             }
7647           else
7648             yield = string_cat(yield, sub);
7649           break;
7650           }
7651
7652         /* quote_lookuptype does lookup-specific quoting */
7653
7654         else
7655           {
7656           int n;
7657           uschar * opt = Ustrchr(arg, '_');
7658
7659           if (opt) *opt++ = 0;
7660
7661           if ((n = search_findtype(arg, Ustrlen(arg))) < 0)
7662             {
7663             expand_string_message = search_error_message;
7664             goto EXPAND_FAILED;
7665             }
7666
7667           if (lookup_list[n]->quote)
7668             sub = (lookup_list[n]->quote)(sub, opt, (unsigned)n);
7669           else if (opt)
7670             sub = NULL;
7671
7672           if (!sub)
7673             {
7674             expand_string_message = string_sprintf(
7675               "\"%s\" unrecognized after \"${quote_%s\"",       /*}*/
7676               opt, arg);
7677             goto EXPAND_FAILED;
7678             }
7679
7680           yield = string_cat(yield, sub);
7681           break;
7682           }
7683
7684         /* rx quote sticks in \ before any non-alphameric character so that
7685         the insertion works in a regular expression. */
7686
7687         case EOP_RXQUOTE:
7688           {
7689           uschar *t = sub - 1;
7690           while (*(++t) != 0)
7691             {
7692             if (!isalnum(*t))
7693               yield = string_catn(yield, US"\\", 1);
7694             yield = string_catn(yield, t, 1);
7695             }
7696           break;
7697           }
7698
7699         /* RFC 2047 encodes, assuming headers_charset (default ISO 8859-1) as
7700         prescribed by the RFC, if there are characters that need to be encoded */
7701
7702         case EOP_RFC2047:
7703           yield = string_cat(yield,
7704                               parse_quote_2047(sub, Ustrlen(sub), headers_charset,
7705                                 FALSE));
7706           break;
7707
7708         /* RFC 2047 decode */
7709
7710         case EOP_RFC2047D:
7711           {
7712           int len;
7713           uschar *error;
7714           uschar *decoded = rfc2047_decode(sub, check_rfc2047_length,
7715             headers_charset, '?', &len, &error);
7716           if (error)
7717             {
7718             expand_string_message = error;
7719             goto EXPAND_FAILED;
7720             }
7721           yield = string_catn(yield, decoded, len);
7722           break;
7723           }
7724
7725         /* from_utf8 converts UTF-8 to 8859-1, turning non-existent chars into
7726         underscores */
7727
7728         case EOP_FROM_UTF8:
7729           {
7730           uschar * buff = store_get(4, sub);
7731           while (*sub)
7732             {
7733             int c;
7734             GETUTF8INC(c, sub);
7735             if (c > 255) c = '_';
7736             buff[0] = c;
7737             yield = string_catn(yield, buff, 1);
7738             }
7739           break;
7740           }
7741
7742         /* replace illegal UTF-8 sequences by replacement character  */
7743
7744         #define UTF8_REPLACEMENT_CHAR US"?"
7745
7746         case EOP_UTF8CLEAN:
7747           {
7748           int seq_len = 0, index = 0;
7749           int bytes_left = 0;
7750           long codepoint = -1;
7751           int complete;
7752           uschar seq_buff[4];                   /* accumulate utf-8 here */
7753
7754           /* Manually track tainting, as we deal in individual chars below */
7755
7756           if (!yield->s || !yield->ptr)
7757             yield->s = store_get(yield->size = Ustrlen(sub), sub);
7758           else if (is_incompatible(yield->s, sub))
7759             gstring_rebuffer(yield, sub);
7760
7761           /* Check the UTF-8, byte-by-byte */
7762
7763           while (*sub)
7764             {
7765             complete = 0;
7766             uschar c = *sub++;
7767
7768             if (bytes_left)
7769               {
7770               if ((c & 0xc0) != 0x80)
7771                       /* wrong continuation byte; invalidate all bytes */
7772                 complete = 1; /* error */
7773               else
7774                 {
7775                 codepoint = (codepoint << 6) | (c & 0x3f);
7776                 seq_buff[index++] = c;
7777                 if (--bytes_left == 0)          /* codepoint complete */
7778                   if(codepoint > 0x10FFFF)      /* is it too large? */
7779                     complete = -1;      /* error (RFC3629 limit) */
7780                   else
7781                     {           /* finished; output utf-8 sequence */
7782                     yield = string_catn(yield, seq_buff, seq_len);
7783                     index = 0;
7784                     }
7785                 }
7786               }
7787             else        /* no bytes left: new sequence */
7788               {
7789               if(!(c & 0x80))   /* 1-byte sequence, US-ASCII, keep it */
7790                 {
7791                 yield = string_catn(yield, &c, 1);
7792                 continue;
7793                 }
7794               if((c & 0xe0) == 0xc0)            /* 2-byte sequence */
7795                 {
7796                 if(c == 0xc0 || c == 0xc1)      /* 0xc0 and 0xc1 are illegal */
7797                   complete = -1;
7798                 else
7799                   {
7800                     bytes_left = 1;
7801                     codepoint = c & 0x1f;
7802                   }
7803                 }
7804               else if((c & 0xf0) == 0xe0)               /* 3-byte sequence */
7805                 {
7806                 bytes_left = 2;
7807                 codepoint = c & 0x0f;
7808                 }
7809               else if((c & 0xf8) == 0xf0)               /* 4-byte sequence */
7810                 {
7811                 bytes_left = 3;
7812                 codepoint = c & 0x07;
7813                 }
7814               else      /* invalid or too long (RFC3629 allows only 4 bytes) */
7815                 complete = -1;
7816
7817               seq_buff[index++] = c;
7818               seq_len = bytes_left + 1;
7819               }         /* if(bytes_left) */
7820
7821             if (complete != 0)
7822               {
7823               bytes_left = index = 0;
7824               yield = string_catn(yield, UTF8_REPLACEMENT_CHAR, 1);
7825               }
7826             if ((complete == 1) && ((c & 0x80) == 0))
7827                           /* ASCII character follows incomplete sequence */
7828                 yield = string_catn(yield, &c, 1);
7829             }
7830           /* If given a sequence truncated mid-character, we also want to report ?
7831           Eg, ${length_1:フィル} is one byte, not one character, so we expect
7832           ${utf8clean:${length_1:フィル}} to yield '?' */
7833
7834           if (bytes_left != 0)
7835             yield = string_catn(yield, UTF8_REPLACEMENT_CHAR, 1);
7836
7837           break;
7838           }
7839
7840 #ifdef SUPPORT_I18N
7841         case EOP_UTF8_DOMAIN_TO_ALABEL:
7842           {
7843           uschar * error = NULL;
7844           uschar * s = string_domain_utf8_to_alabel(sub, &error);
7845           if (error)
7846             {
7847             expand_string_message = string_sprintf(
7848               "error converting utf8 (%s) to alabel: %s",
7849               string_printing(sub), error);
7850             goto EXPAND_FAILED;
7851             }
7852           yield = string_cat(yield, s);
7853           break;
7854           }
7855
7856         case EOP_UTF8_DOMAIN_FROM_ALABEL:
7857           {
7858           uschar * error = NULL;
7859           uschar * s = string_domain_alabel_to_utf8(sub, &error);
7860           if (error)
7861             {
7862             expand_string_message = string_sprintf(
7863               "error converting alabel (%s) to utf8: %s",
7864               string_printing(sub), error);
7865             goto EXPAND_FAILED;
7866             }
7867           yield = string_cat(yield, s);
7868           break;
7869           }
7870
7871         case EOP_UTF8_LOCALPART_TO_ALABEL:
7872           {
7873           uschar * error = NULL;
7874           uschar * s = string_localpart_utf8_to_alabel(sub, &error);
7875           if (error)
7876             {
7877             expand_string_message = string_sprintf(
7878               "error converting utf8 (%s) to alabel: %s",
7879               string_printing(sub), error);
7880             goto EXPAND_FAILED;
7881             }
7882           yield = string_cat(yield, s);
7883           DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", yield->s);
7884           break;
7885           }
7886
7887         case EOP_UTF8_LOCALPART_FROM_ALABEL:
7888           {
7889           uschar * error = NULL;
7890           uschar * s = string_localpart_alabel_to_utf8(sub, &error);
7891           if (error)
7892             {
7893             expand_string_message = string_sprintf(
7894               "error converting alabel (%s) to utf8: %s",
7895               string_printing(sub), error);
7896             goto EXPAND_FAILED;
7897             }
7898           yield = string_cat(yield, s);
7899           break;
7900           }
7901 #endif  /* EXPERIMENTAL_INTERNATIONAL */
7902
7903         /* escape turns all non-printing characters into escape sequences. */
7904
7905         case EOP_ESCAPE:
7906           {
7907           const uschar * t = string_printing(sub);
7908           yield = string_cat(yield, t);
7909           break;
7910           }
7911
7912         case EOP_ESCAPE8BIT:
7913           {
7914           uschar c;
7915
7916           for (const uschar * s = sub; (c = *s); s++)
7917             yield = c < 127 && c != '\\'
7918               ? string_catn(yield, s, 1)
7919               : string_fmt_append(yield, "\\%03o", c);
7920           break;
7921           }
7922
7923         /* Handle numeric expression evaluation */
7924
7925         case EOP_EVAL:
7926         case EOP_EVAL10:
7927           {
7928           uschar *save_sub = sub;
7929           uschar *error = NULL;
7930           int_eximarith_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
7931           if (error)
7932             {
7933             expand_string_message = string_sprintf("error in expression "
7934               "evaluation: %s (after processing \"%.*s\")", error,
7935               (int)(sub-save_sub), save_sub);
7936             goto EXPAND_FAILED;
7937             }
7938           yield = string_fmt_append(yield, PR_EXIM_ARITH, n);
7939           break;
7940           }
7941
7942         /* Handle time period formatting */
7943
7944         case EOP_TIME_EVAL:
7945           {
7946           int n = readconf_readtime(sub, 0, FALSE);
7947           if (n < 0)
7948             {
7949             expand_string_message = string_sprintf("string \"%s\" is not an "
7950               "Exim time interval in \"%s\" operator", sub, name);
7951             goto EXPAND_FAILED;
7952             }
7953           yield = string_fmt_append(yield, "%d", n);
7954           break;
7955           }
7956
7957         case EOP_TIME_INTERVAL:
7958           {
7959           int n;
7960           uschar *t = read_number(&n, sub);
7961           if (*t != 0) /* Not A Number*/
7962             {
7963             expand_string_message = string_sprintf("string \"%s\" is not a "
7964               "positive number in \"%s\" operator", sub, name);
7965             goto EXPAND_FAILED;
7966             }
7967           t = readconf_printtime(n);
7968           yield = string_cat(yield, t);
7969           break;
7970           }
7971
7972         /* Convert string to base64 encoding */
7973
7974         case EOP_STR2B64:
7975         case EOP_BASE64:
7976           {
7977 #ifndef DISABLE_TLS
7978           uschar * s = vp && *(void **)vp->value
7979             ? tls_cert_der_b64(*(void **)vp->value)
7980             : b64encode(CUS sub, Ustrlen(sub));
7981 #else
7982           uschar * s = b64encode(CUS sub, Ustrlen(sub));
7983 #endif
7984           yield = string_cat(yield, s);
7985           break;
7986           }
7987
7988         case EOP_BASE64D:
7989           {
7990           uschar * s;
7991           int len = b64decode(sub, &s);
7992           if (len < 0)
7993             {
7994             expand_string_message = string_sprintf("string \"%s\" is not "
7995               "well-formed for \"%s\" operator", sub, name);
7996             goto EXPAND_FAILED;
7997             }
7998           yield = string_cat(yield, s);
7999           break;
8000           }
8001
8002         /* strlen returns the length of the string */
8003
8004         case EOP_STRLEN:
8005           yield = string_fmt_append(yield, "%d", Ustrlen(sub));
8006           break;
8007
8008         /* length_n or l_n takes just the first n characters or the whole string,
8009         whichever is the shorter;
8010
8011         substr_m_n, and s_m_n take n characters from offset m; negative m take
8012         from the end; l_n is synonymous with s_0_n. If n is omitted in substr it
8013         takes the rest, either to the right or to the left.
8014
8015         hash_n or h_n makes a hash of length n from the string, yielding n
8016         characters from the set a-z; hash_n_m makes a hash of length n, but
8017         uses m characters from the set a-zA-Z0-9.
8018
8019         nhash_n returns a single number between 0 and n-1 (in text form), while
8020         nhash_n_m returns a div/mod hash as two numbers "a/b". The first lies
8021         between 0 and n-1 and the second between 0 and m-1. */
8022
8023         case EOP_LENGTH:
8024         case EOP_L:
8025         case EOP_SUBSTR:
8026         case EOP_S:
8027         case EOP_HASH:
8028         case EOP_H:
8029         case EOP_NHASH:
8030         case EOP_NH:
8031           {
8032           int sign = 1;
8033           int value1 = 0;
8034           int value2 = -1;
8035           int *pn;
8036           int len;
8037           uschar *ret;
8038
8039           if (!arg)
8040             {
8041             expand_string_message = string_sprintf("missing values after %s",
8042               name);
8043             goto EXPAND_FAILED;
8044             }
8045
8046           /* "length" has only one argument, effectively being synonymous with
8047           substr_0_n. */
8048
8049           if (c == EOP_LENGTH || c == EOP_L)
8050             {
8051             pn = &value2;
8052             value2 = 0;
8053             }
8054
8055           /* The others have one or two arguments; for "substr" the first may be
8056           negative. The second being negative means "not supplied". */
8057
8058           else
8059             {
8060             pn = &value1;
8061             if (name[0] == 's' && *arg == '-') { sign = -1; arg++; }
8062             }
8063
8064           /* Read up to two numbers, separated by underscores */
8065
8066           ret = arg;
8067           while (*arg != 0)
8068             {
8069             if (arg != ret && *arg == '_' && pn == &value1)
8070               {
8071               pn = &value2;
8072               value2 = 0;
8073               if (arg[1] != 0) arg++;
8074               }
8075             else if (!isdigit(*arg))
8076               {
8077               expand_string_message =
8078                 string_sprintf("non-digit after underscore in \"%s\"", name);
8079               goto EXPAND_FAILED;
8080               }
8081             else *pn = (*pn)*10 + *arg++ - '0';
8082             }
8083           value1 *= sign;
8084
8085           /* Perform the required operation */
8086
8087           ret = c == EOP_HASH || c == EOP_H
8088             ? compute_hash(sub, value1, value2, &len)
8089             : c == EOP_NHASH || c == EOP_NH
8090             ? compute_nhash(sub, value1, value2, &len)
8091             : extract_substr(sub, value1, value2, &len);
8092           if (!ret) goto EXPAND_FAILED;
8093
8094           yield = string_catn(yield, ret, len);
8095           break;
8096           }
8097
8098         /* Stat a path */
8099
8100         case EOP_STAT:
8101           {
8102           uschar smode[12];
8103           uschar **modetable[3];
8104           mode_t mode;
8105           struct stat st;
8106
8107           if (expand_forbid & RDO_EXISTS)
8108             {
8109             expand_string_message = US"Use of the stat() expansion is not permitted";
8110             goto EXPAND_FAILED;
8111             }
8112
8113           if (stat(CS sub, &st) < 0)
8114             {
8115             expand_string_message = string_sprintf("stat(%s) failed: %s",
8116               sub, strerror(errno));
8117             goto EXPAND_FAILED;
8118             }
8119           mode = st.st_mode;
8120           switch (mode & S_IFMT)
8121             {
8122             case S_IFIFO: smode[0] = 'p'; break;
8123             case S_IFCHR: smode[0] = 'c'; break;
8124             case S_IFDIR: smode[0] = 'd'; break;
8125             case S_IFBLK: smode[0] = 'b'; break;
8126             case S_IFREG: smode[0] = '-'; break;
8127             default: smode[0] = '?'; break;
8128             }
8129
8130           modetable[0] = ((mode & 01000) == 0)? mtable_normal : mtable_sticky;
8131           modetable[1] = ((mode & 02000) == 0)? mtable_normal : mtable_setid;
8132           modetable[2] = ((mode & 04000) == 0)? mtable_normal : mtable_setid;
8133
8134           for (int i = 0; i < 3; i++)
8135             {
8136             memcpy(CS(smode + 7 - i*3), CS(modetable[i][mode & 7]), 3);
8137             mode >>= 3;
8138             }
8139
8140           smode[10] = 0;
8141           yield = string_fmt_append(yield,
8142             "mode=%04lo smode=%s inode=%ld device=%ld links=%ld "
8143             "uid=%ld gid=%ld size=" OFF_T_FMT " atime=%ld mtime=%ld ctime=%ld",
8144             (long)(st.st_mode & 077777), smode, (long)st.st_ino,
8145             (long)st.st_dev, (long)st.st_nlink, (long)st.st_uid,
8146             (long)st.st_gid, st.st_size, (long)st.st_atime,
8147             (long)st.st_mtime, (long)st.st_ctime);
8148           break;
8149           }
8150
8151         /* vaguely random number less than N */
8152
8153         case EOP_RANDINT:
8154           {
8155           int_eximarith_t max = expanded_string_integer(sub, TRUE);
8156
8157           if (expand_string_message)
8158             goto EXPAND_FAILED;
8159           yield = string_fmt_append(yield, "%d", vaguely_random_number((int)max));
8160           break;
8161           }
8162
8163         /* Reverse IP, including IPv6 to dotted-nibble */
8164
8165         case EOP_REVERSE_IP:
8166           {
8167           int family, maskptr;
8168           uschar reversed[128];
8169
8170           family = string_is_ip_address(sub, &maskptr);
8171           if (family == 0)
8172             {
8173             expand_string_message = string_sprintf(
8174                 "reverse_ip() not given an IP address [%s]", sub);
8175             goto EXPAND_FAILED;
8176             }
8177           invert_address(reversed, sub);
8178           yield = string_cat(yield, reversed);
8179           break;
8180           }
8181
8182         /* Unknown operator */
8183
8184         default:
8185           expand_string_message =
8186             string_sprintf("unknown expansion operator \"%s\"", name);
8187           goto EXPAND_FAILED;
8188         }       /* EOP_* switch */
8189
8190        DEBUG(D_expand)
8191         {
8192         const uschar * s = yield->s + start;
8193         int i = yield->ptr - start;
8194         BOOL tainted = is_tainted(s);
8195
8196         DEBUG(D_noutf8)
8197           {
8198           debug_printf_indent("|-----op-res: %.*s\n", i, s);
8199           if (tainted)
8200             {
8201             debug_printf_indent("%s     \\__", flags & ESI_SKIPPING ? "|     " : "      ");
8202             debug_print_taint(yield->s);
8203             }
8204           }
8205         else
8206           {
8207           debug_printf_indent(UTF8_VERT_RIGHT
8208             UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
8209             "op-res: %.*s\n", i, s);
8210           if (tainted)
8211             {
8212             debug_printf_indent("%s",
8213               flags & ESI_SKIPPING
8214               ? UTF8_VERT "             " : "           " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ);
8215             debug_print_taint(yield->s);
8216             }
8217           }
8218         }
8219        continue;
8220        }
8221     }
8222
8223   /* Not an item or an operator */
8224   /* Handle a plain name. If this is the first thing in the expansion, release
8225   the pre-allocated buffer. If the result data is known to be in a new buffer,
8226   newsize will be set to the size of that buffer, and we can just point at that
8227   store instead of copying. Many expansion strings contain just one reference,
8228   so this is a useful optimization, especially for humungous headers
8229   ($message_headers). */
8230                                                 /*{*/
8231   if (*s++ == '}')
8232     {
8233     const uschar * value;
8234     int len;
8235     int newsize = 0;
8236     gstring * g = NULL;
8237
8238     if (!yield)
8239       g = store_get(sizeof(gstring), GET_UNTAINTED);
8240     else if (yield->ptr == 0)
8241       {
8242       if (resetok) reset_point = store_reset(reset_point);
8243       yield = NULL;
8244       reset_point = store_mark();
8245       g = store_get(sizeof(gstring), GET_UNTAINTED);    /* alloc _before_ calling find_variable() */
8246       }
8247     if (!(value = find_variable(name, FALSE, !!(flags & ESI_SKIPPING), &newsize)))
8248       {
8249       expand_string_message =
8250         string_sprintf("unknown variable in \"${%s}\"", name);
8251       check_variable_error_message(name);
8252       goto EXPAND_FAILED;
8253       }
8254     len = Ustrlen(value);
8255     if (!yield && newsize)
8256       {
8257       yield = g;
8258       yield->size = newsize;
8259       yield->ptr = len;
8260       yield->s = US value; /* known to be in new store i.e. a copy, so deconst safe */
8261       }
8262     else
8263       yield = string_catn(yield, value, len);
8264     continue;
8265     }
8266
8267   /* Else there's something wrong */
8268
8269   expand_string_message =
8270     string_sprintf("\"${%s\" is not a known operator (or a } is missing "
8271     "in a variable reference)", name);
8272   goto EXPAND_FAILED;
8273   }
8274
8275 /* If we hit the end of the string when brace_ends is set, there is a missing
8276 terminating brace. */
8277
8278 if (flags & ESI_BRACE_ENDS && !*s)
8279   {                                                     /*{{*/
8280   expand_string_message = malformed_header
8281     ? US"missing } at end of string - could be header name not terminated by colon"
8282     : US"missing } at end of string";
8283   goto EXPAND_FAILED;
8284   }
8285
8286 /* Expansion succeeded; yield may still be NULL here if nothing was actually
8287 added to the string. If so, set up an empty string. Add a terminating zero. If
8288 left != NULL, return a pointer to the terminator. */
8289
8290 if (!yield)
8291   yield = string_get(1);
8292 (void) string_from_gstring(yield);
8293 if (left) *left = s;
8294
8295 /* Any stacking store that was used above the final string is no longer needed.
8296 In many cases the final string will be the first one that was got and so there
8297 will be optimal store usage. */
8298
8299 if (resetok) gstring_release_unused(yield);
8300 else if (resetok_p) *resetok_p = FALSE;
8301
8302 DEBUG(D_expand)
8303   {
8304   BOOL tainted = is_tainted(yield->s);
8305   DEBUG(D_noutf8)
8306     {
8307     debug_printf_indent("|--expanding: %.*s\n", (int)(s - string), string);
8308     debug_printf_indent("%sresult: %s\n",
8309       flags & ESI_SKIPPING ? "|-----" : "\\_____", yield->s);
8310     if (tainted)
8311       {
8312       debug_printf_indent("%s     \\__", flags & ESI_SKIPPING ? "|     " : "      ");
8313       debug_print_taint(yield->s);
8314       }
8315     if (flags & ESI_SKIPPING)
8316       debug_printf_indent("\\___skipping: result is not used\n");
8317     }
8318   else
8319     {
8320     debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
8321       "expanding: %.*s\n",
8322       (int)(s - string), string);
8323     debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
8324       "result: %s\n",
8325       flags & ESI_SKIPPING ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
8326       yield->s);
8327     if (tainted)
8328       {
8329       debug_printf_indent("%s",
8330         flags & ESI_SKIPPING
8331         ? UTF8_VERT "             " : "           " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ);
8332       debug_print_taint(yield->s);
8333       }
8334     if (flags & ESI_SKIPPING)
8335       debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
8336         "skipping: result is not used\n");
8337     }
8338   }
8339 if (textonly_p) *textonly_p = textonly;
8340 expand_level--;
8341 return yield->s;
8342
8343 /* This is the failure exit: easiest to program with a goto. We still need
8344 to update the pointer to the terminator, for cases of nested calls with "fail".
8345 */
8346
8347 EXPAND_FAILED_CURLY:
8348 if (malformed_header)
8349   expand_string_message =
8350     US"missing or misplaced { or } - could be header name not terminated by colon";
8351
8352 else if (!expand_string_message || !*expand_string_message)
8353   expand_string_message = US"missing or misplaced { or }";
8354
8355 /* At one point, Exim reset the store to yield (if yield was not NULL), but
8356 that is a bad idea, because expand_string_message is in dynamic store. */
8357
8358 EXPAND_FAILED:
8359 if (left) *left = s;
8360 DEBUG(D_expand)
8361   {
8362   DEBUG(D_noutf8)
8363     {
8364     debug_printf_indent("|failed to expand: %s\n", string);
8365     debug_printf_indent("%serror message: %s\n",
8366       f.expand_string_forcedfail ? "|---" : "\\___", expand_string_message);
8367     if (f.expand_string_forcedfail)
8368       debug_printf_indent("\\failure was forced\n");
8369     }
8370   else
8371     {
8372     debug_printf_indent(UTF8_VERT_RIGHT "failed to expand: %s\n",
8373       string);
8374     debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
8375       "error message: %s\n",
8376       f.expand_string_forcedfail ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
8377       expand_string_message);
8378     if (f.expand_string_forcedfail)
8379       debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n");
8380     }
8381   }
8382 if (resetok_p && !resetok) *resetok_p = FALSE;
8383 expand_level--;
8384 return NULL;
8385 }
8386
8387
8388
8389 /* This is the external function call. Do a quick check for any expansion
8390 metacharacters, and if there are none, just return the input string.
8391
8392 Arguments
8393         the string to be expanded
8394         optional pointer for return boolean indicating no-dynamic-expansions
8395
8396 Returns:  the expanded string, or NULL if expansion failed; if failure was
8397           due to a lookup deferring, search_find_defer will be TRUE
8398 */
8399
8400 const uschar *
8401 expand_string_2(const uschar * string, BOOL * textonly_p)
8402 {
8403 if (Ustrpbrk(string, "$\\") != NULL)
8404   {
8405   int old_pool = store_pool;
8406   uschar * s;
8407
8408   f.search_find_defer = FALSE;
8409   malformed_header = FALSE;
8410   store_pool = POOL_MAIN;
8411     s = expand_string_internal(string, ESI_HONOR_DOLLAR, NULL, NULL, textonly_p);
8412   store_pool = old_pool;
8413   return s;
8414   }
8415 if (textonly_p) *textonly_p = TRUE;
8416 return string;
8417 }
8418
8419 const uschar *
8420 expand_cstring(const uschar * string)
8421 { return expand_string_2(string, NULL); }
8422
8423 uschar *
8424 expand_string(uschar * string)
8425 { return US expand_string_2(CUS string, NULL); }
8426
8427
8428
8429
8430
8431
8432 /*************************************************
8433 *              Expand and copy                   *
8434 *************************************************/
8435
8436 /* Now and again we want to expand a string and be sure that the result is in a
8437 new bit of store. This function does that.
8438 Since we know it has been copied, the de-const cast is safe.
8439
8440 Argument: the string to be expanded
8441 Returns:  the expanded string, always in a new bit of store, or NULL
8442 */
8443
8444 uschar *
8445 expand_string_copy(const uschar *string)
8446 {
8447 const uschar *yield = expand_cstring(string);
8448 if (yield == string) yield = string_copy(string);
8449 return US yield;
8450 }
8451
8452
8453
8454 /*************************************************
8455 *        Expand and interpret as an integer      *
8456 *************************************************/
8457
8458 /* Expand a string, and convert the result into an integer.
8459
8460 Arguments:
8461   string  the string to be expanded
8462   isplus  TRUE if a non-negative number is expected
8463
8464 Returns:  the integer value, or
8465           -1 for an expansion error               ) in both cases, message in
8466           -2 for an integer interpretation error  ) expand_string_message
8467           expand_string_message is set NULL for an OK integer
8468 */
8469
8470 int_eximarith_t
8471 expand_string_integer(uschar *string, BOOL isplus)
8472 {
8473 return expanded_string_integer(expand_string(string), isplus);
8474 }
8475
8476
8477 /*************************************************
8478  *         Interpret string as an integer        *
8479  *************************************************/
8480
8481 /* Convert a string (that has already been expanded) into an integer.
8482
8483 This function is used inside the expansion code.
8484
8485 Arguments:
8486   s       the string to be expanded
8487   isplus  TRUE if a non-negative number is expected
8488
8489 Returns:  the integer value, or
8490           -1 if string is NULL (which implies an expansion error)
8491           -2 for an integer interpretation error
8492           expand_string_message is set NULL for an OK integer
8493 */
8494
8495 static int_eximarith_t
8496 expanded_string_integer(const uschar *s, BOOL isplus)
8497 {
8498 int_eximarith_t value;
8499 uschar *msg = US"invalid integer \"%s\"";
8500 uschar *endptr;
8501
8502 /* If expansion failed, expand_string_message will be set. */
8503
8504 if (!s) return -1;
8505
8506 /* On an overflow, strtol() returns LONG_MAX or LONG_MIN, and sets errno
8507 to ERANGE. When there isn't an overflow, errno is not changed, at least on some
8508 systems, so we set it zero ourselves. */
8509
8510 errno = 0;
8511 expand_string_message = NULL;               /* Indicates no error */
8512
8513 /* Before Exim 4.64, strings consisting entirely of whitespace compared
8514 equal to 0.  Unfortunately, people actually relied upon that, so preserve
8515 the behaviour explicitly.  Stripping leading whitespace is a harmless
8516 noop change since strtol skips it anyway (provided that there is a number
8517 to find at all). */
8518 if (isspace(*s))
8519   if (Uskip_whitespace(&s) == '\0')
8520     {
8521       DEBUG(D_expand)
8522        debug_printf_indent("treating blank string as number 0\n");
8523       return 0;
8524     }
8525
8526 value = strtoll(CS s, CSS &endptr, 10);
8527
8528 if (endptr == s)
8529   msg = US"integer expected but \"%s\" found";
8530 else if (value < 0 && isplus)
8531   msg = US"non-negative integer expected but \"%s\" found";
8532 else
8533   {
8534   switch (tolower(*endptr))
8535     {
8536     default:
8537       break;
8538     case 'k':
8539       if (value > EXIM_ARITH_MAX/1024 || value < EXIM_ARITH_MIN/1024) errno = ERANGE;
8540       else value *= 1024;
8541       endptr++;
8542       break;
8543     case 'm':
8544       if (value > EXIM_ARITH_MAX/(1024*1024) || value < EXIM_ARITH_MIN/(1024*1024)) errno = ERANGE;
8545       else value *= 1024*1024;
8546       endptr++;
8547       break;
8548     case 'g':
8549       if (value > EXIM_ARITH_MAX/(1024*1024*1024) || value < EXIM_ARITH_MIN/(1024*1024*1024)) errno = ERANGE;
8550       else value *= 1024*1024*1024;
8551       endptr++;
8552       break;
8553     }
8554   if (errno == ERANGE)
8555     msg = US"absolute value of integer \"%s\" is too large (overflow)";
8556   else
8557     if (Uskip_whitespace(&endptr) == 0) return value;
8558   }
8559
8560 expand_string_message = string_sprintf(CS msg, s);
8561 return -2;
8562 }
8563
8564
8565 /* These values are usually fixed boolean values, but they are permitted to be
8566 expanded strings.
8567
8568 Arguments:
8569   addr       address being routed
8570   mtype      the module type
8571   mname      the module name
8572   dbg_opt    debug selectors
8573   oname      the option name
8574   bvalue     the router's boolean value
8575   svalue     the router's string value
8576   rvalue     where to put the returned value
8577
8578 Returns:     OK     value placed in rvalue
8579              DEFER  expansion failed
8580 */
8581
8582 int
8583 exp_bool(address_item *addr,
8584   uschar *mtype, uschar *mname, unsigned dbg_opt,
8585   uschar *oname, BOOL bvalue,
8586   uschar *svalue, BOOL *rvalue)
8587 {
8588 uschar *expanded;
8589 if (!svalue) { *rvalue = bvalue; return OK; }
8590
8591 if (!(expanded = expand_string(svalue)))
8592   {
8593   if (f.expand_string_forcedfail)
8594     {
8595     DEBUG(dbg_opt) debug_printf("expansion of \"%s\" forced failure\n", oname);
8596     *rvalue = bvalue;
8597     return OK;
8598     }
8599   addr->message = string_sprintf("failed to expand \"%s\" in %s %s: %s",
8600       oname, mname, mtype, expand_string_message);
8601   DEBUG(dbg_opt) debug_printf("%s\n", addr->message);
8602   return DEFER;
8603   }
8604
8605 DEBUG(dbg_opt) debug_printf("expansion of \"%s\" yields \"%s\"\n", oname,
8606   expanded);
8607
8608 if (strcmpic(expanded, US"true") == 0 || strcmpic(expanded, US"yes") == 0)
8609   *rvalue = TRUE;
8610 else if (strcmpic(expanded, US"false") == 0 || strcmpic(expanded, US"no") == 0)
8611   *rvalue = FALSE;
8612 else
8613   {
8614   addr->message = string_sprintf("\"%s\" is not a valid value for the "
8615     "\"%s\" option in the %s %s", expanded, oname, mname, mtype);
8616   return DEFER;
8617   }
8618
8619 return OK;
8620 }
8621
8622
8623
8624 /* Avoid potentially exposing a password in a string about to be logged */
8625
8626 uschar *
8627 expand_hide_passwords(uschar * s)
8628 {
8629 return (  (  Ustrstr(s, "failed to expand") != NULL
8630           || Ustrstr(s, "expansion of ")    != NULL
8631           )
8632        && (  Ustrstr(s, "mysql")   != NULL
8633           || Ustrstr(s, "pgsql")   != NULL
8634           || Ustrstr(s, "redis")   != NULL
8635           || Ustrstr(s, "sqlite")  != NULL
8636           || Ustrstr(s, "ldap:")   != NULL
8637           || Ustrstr(s, "ldaps:")  != NULL
8638           || Ustrstr(s, "ldapi:")  != NULL
8639           || Ustrstr(s, "ldapdn:") != NULL
8640           || Ustrstr(s, "ldapm:")  != NULL
8641        )  )
8642   ? US"Temporary internal error" : s;
8643 }
8644
8645
8646 /* Read given named file into big_buffer.  Use for keying material etc.
8647 The content will have an ascii NUL appended.
8648
8649 Arguments:
8650  filename       as it says
8651
8652 Return:  pointer to buffer, or NULL on error.
8653 */
8654
8655 uschar *
8656 expand_file_big_buffer(const uschar * filename)
8657 {
8658 int fd, off = 0, len;
8659
8660 if ((fd = exim_open2(CS filename, O_RDONLY)) < 0)
8661   {
8662   log_write(0, LOG_MAIN | LOG_PANIC, "unable to open file for reading: %s",
8663              filename);
8664   return NULL;
8665   }
8666
8667 do
8668   {
8669   if ((len = read(fd, big_buffer + off, big_buffer_size - 2 - off)) < 0)
8670     {
8671     (void) close(fd);
8672     log_write(0, LOG_MAIN|LOG_PANIC, "unable to read file: %s", filename);
8673     return NULL;
8674     }
8675   off += len;
8676   }
8677 while (len > 0);
8678
8679 (void) close(fd);
8680 big_buffer[off] = '\0';
8681 return big_buffer;
8682 }
8683
8684
8685
8686 /*************************************************
8687 * Error-checking for testsuite                   *
8688 *************************************************/
8689 typedef struct {
8690   uschar *      region_start;
8691   uschar *      region_end;
8692   const uschar *var_name;
8693   const uschar *var_data;
8694 } err_ctx;
8695
8696 /* Called via tree_walk, which allows nonconst name/data.  Our usage is const. */
8697 static void
8698 assert_variable_notin(uschar * var_name, uschar * var_data, void * ctx)
8699 {
8700 err_ctx * e = ctx;
8701 if (var_data >= e->region_start  &&  var_data < e->region_end)
8702   {
8703   e->var_name = CUS var_name;
8704   e->var_data = CUS var_data;
8705   }
8706 }
8707
8708 void
8709 assert_no_variables(void * ptr, int len, const char * filename, int linenumber)
8710 {
8711 err_ctx e = { .region_start = ptr, .region_end = US ptr + len,
8712               .var_name = NULL, .var_data = NULL };
8713
8714 /* check acl_ variables */
8715 tree_walk(acl_var_c, assert_variable_notin, &e);
8716 tree_walk(acl_var_m, assert_variable_notin, &e);
8717
8718 /* check auth<n> variables.
8719 assert_variable_notin() treats as const, so deconst is safe. */
8720 for (int i = 0; i < AUTH_VARS; i++) if (auth_vars[i])
8721   assert_variable_notin(US"auth<n>", US auth_vars[i], &e);
8722
8723 #ifdef WITH_CONTENT_SCAN
8724 /* check regex<n> variables. assert_variable_notin() treats as const. */
8725 for (int i = 0; i < REGEX_VARS; i++) if (regex_vars[i])
8726   assert_variable_notin(US"regex<n>", US regex_vars[i], &e);
8727 #endif
8728
8729 /* check known-name variables */
8730 for (var_entry * v = var_table; v < var_table + var_table_size; v++)
8731   if (v->type == vtype_stringptr)
8732     assert_variable_notin(US v->name, *(USS v->value), &e);
8733
8734 /* check dns and address trees */
8735 tree_walk(tree_dns_fails,     assert_variable_notin, &e);
8736 tree_walk(tree_duplicates,    assert_variable_notin, &e);
8737 tree_walk(tree_nonrecipients, assert_variable_notin, &e);
8738 tree_walk(tree_unusable,      assert_variable_notin, &e);
8739
8740 if (e.var_name)
8741   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
8742     "live variable '%s' destroyed by reset_store at %s:%d\n- value '%.64s'",
8743     e.var_name, filename, linenumber, e.var_data);
8744 }
8745
8746
8747
8748 /*************************************************
8749 **************************************************
8750 *             Stand-alone test program           *
8751 **************************************************
8752 *************************************************/
8753
8754 #ifdef STAND_ALONE
8755
8756
8757 BOOL
8758 regex_match_and_setup(const pcre2_code *re, uschar *subject, int options, int setup)
8759 {
8760 int ovec[3*(EXPAND_MAXN+1)];
8761 int n = pcre_exec(re, NULL, subject, Ustrlen(subject), 0, PCRE_EOPT|options,
8762   ovec, nelem(ovec));
8763 BOOL yield = n >= 0;
8764 if (n == 0) n = EXPAND_MAXN + 1;
8765 if (yield)
8766   {
8767   expand_nmax = setup < 0 ? 0 : setup + 1;
8768   for (int nn = setup < 0 ? 0 : 2; nn < n*2; nn += 2)
8769     {
8770     expand_nstring[expand_nmax] = subject + ovec[nn];
8771     expand_nlength[expand_nmax++] = ovec[nn+1] - ovec[nn];
8772     }
8773   expand_nmax--;
8774   }
8775 return yield;
8776 }
8777
8778
8779 int main(int argc, uschar **argv)
8780 {
8781 uschar buffer[1024];
8782
8783 debug_selector = D_v;
8784 debug_file = stderr;
8785 debug_fd = fileno(debug_file);
8786 big_buffer = malloc(big_buffer_size);
8787 store_init();
8788
8789 for (int i = 1; i < argc; i++)
8790   {
8791   if (argv[i][0] == '+')
8792     {
8793     debug_trace_memory = 2;
8794     argv[i]++;
8795     }
8796   if (isdigit(argv[i][0]))
8797     debug_selector = Ustrtol(argv[i], NULL, 0);
8798   else
8799     if (Ustrspn(argv[i], "abcdefghijklmnopqrtsuvwxyz0123456789-.:/") ==
8800         Ustrlen(argv[i]))
8801       {
8802 #ifdef LOOKUP_LDAP
8803       eldap_default_servers = argv[i];
8804 #endif
8805 #ifdef LOOKUP_MYSQL
8806       mysql_servers = argv[i];
8807 #endif
8808 #ifdef LOOKUP_PGSQL
8809       pgsql_servers = argv[i];
8810 #endif
8811 #ifdef LOOKUP_REDIS
8812       redis_servers = argv[i];
8813 #endif
8814       }
8815 #ifdef EXIM_PERL
8816   else opt_perl_startup = argv[i];
8817 #endif
8818   }
8819
8820 printf("Testing string expansion: debug_level = %d\n\n", debug_level);
8821
8822 expand_nstring[1] = US"string 1....";
8823 expand_nlength[1] = 8;
8824 expand_nmax = 1;
8825
8826 #ifdef EXIM_PERL
8827 if (opt_perl_startup != NULL)
8828   {
8829   uschar *errstr;
8830   printf("Starting Perl interpreter\n");
8831   errstr = init_perl(opt_perl_startup);
8832   if (errstr != NULL)
8833     {
8834     printf("** error in perl_startup code: %s\n", errstr);
8835     return EXIT_FAILURE;
8836     }
8837   }
8838 #endif /* EXIM_PERL */
8839
8840 /* Thie deliberately regards the input as untainted, so that it can be
8841 expanded; only reasonable since this is a test for string-expansions. */
8842
8843 while (fgets(buffer, sizeof(buffer), stdin) != NULL)
8844   {
8845   rmark reset_point = store_mark();
8846   uschar *yield = expand_string(buffer);
8847   if (yield)
8848     printf("%s\n", yield);
8849   else
8850     {
8851     if (f.search_find_defer) printf("search_find deferred\n");
8852     printf("Failed: %s\n", expand_string_message);
8853     if (f.expand_string_forcedfail) printf("Forced failure\n");
8854     printf("\n");
8855     }
8856   store_reset(reset_point);
8857   }
8858
8859 search_tidyup();
8860
8861 return 0;
8862 }
8863
8864 #endif
8865
8866 /* vi: aw ai sw=2
8867 */
8868 /* End of expand.c */