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