65c585d1c0cd6641eedcc52429ee6f7c33f76fb3
[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 /*  Return offset in ops table, or -1 if not found.
2251 Repoint to just after the operator in the string.
2252
2253 Argument:
2254  ss     string representation of operator
2255  opname split-out operator name
2256 */
2257
2258 static int
2259 identify_operator(const uschar ** ss, uschar ** opname)
2260 {
2261 const uschar * s = *ss;
2262 uschar name[256];
2263
2264 /* Numeric comparisons are symbolic */
2265
2266 if (*s == '=' || *s == '>' || *s == '<')
2267   {
2268   int p = 0;
2269   name[p++] = *s++;
2270   if (*s == '=')
2271     {
2272     name[p++] = '=';
2273     s++;
2274     }
2275   name[p] = 0;
2276   }
2277
2278 /* All other conditions are named */
2279
2280 else
2281   s = read_name(name, sizeof(name), s, US"_");
2282 *ss = s;
2283
2284 /* If we haven't read a name, it means some non-alpha character is first. */
2285
2286 if (!name[0])
2287   {
2288   expand_string_message = string_sprintf("condition name expected, "
2289     "but found \"%.16s\"", s);
2290   return -1;
2291   }
2292 if (opname)
2293   *opname = string_copy(name);
2294
2295 return chop_match(name, cond_table, nelem(cond_table));
2296 }
2297
2298
2299 /*************************************************
2300 *        Read and evaluate a condition           *
2301 *************************************************/
2302
2303 /*
2304 Arguments:
2305   s        points to the start of the condition text
2306   resetok  points to a BOOL which is written false if it is unsafe to
2307            free memory. Certain condition types (acl) may have side-effect
2308            allocation which must be preserved.
2309   yield    points to a BOOL to hold the result of the condition test;
2310            if NULL, we are just reading through a condition that is
2311            part of an "or" combination to check syntax, or in a state
2312            where the answer isn't required
2313
2314 Returns:   a pointer to the first character after the condition, or
2315            NULL after an error
2316 */
2317
2318 static const uschar *
2319 eval_condition(const uschar *s, BOOL *resetok, BOOL *yield)
2320 {
2321 BOOL testfor = TRUE;
2322 BOOL tempcond, combined_cond;
2323 BOOL *subcondptr;
2324 BOOL sub2_honour_dollar = TRUE;
2325 BOOL is_forany, is_json, is_jsons;
2326 int rc, cond_type, roffset;
2327 int_eximarith_t num[2];
2328 struct stat statbuf;
2329 uschar * opname;
2330 uschar name[256];
2331 const uschar *sub[10];
2332
2333 const pcre *re;
2334 const uschar *rerror;
2335
2336 for (;;)
2337   {
2338   while (isspace(*s)) s++;
2339   if (*s == '!') { testfor = !testfor; s++; } else break;
2340   }
2341
2342 switch(cond_type = identify_operator(&s, &opname))
2343   {
2344   /* def: tests for a non-empty variable, or for the existence of a header. If
2345   yield == NULL we are in a skipping state, and don't care about the answer. */
2346
2347   case ECOND_DEF:
2348     {
2349     uschar * t;
2350
2351     if (*s != ':')
2352       {
2353       expand_string_message = US"\":\" expected after \"def\"";
2354       return NULL;
2355       }
2356
2357     s = read_name(name, 256, s+1, US"_");
2358
2359     /* Test for a header's existence. If the name contains a closing brace
2360     character, this may be a user error where the terminating colon has been
2361     omitted. Set a flag to adjust a subsequent error message in this case. */
2362
2363     if (  ( *(t = name) == 'h'
2364           || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
2365           )
2366        && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
2367        )
2368       {
2369       s = read_header_name(name, 256, s);
2370       /* {-for-text-editors */
2371       if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
2372       if (yield) *yield =
2373         (find_header(name, NULL, FH_EXISTS_ONLY, NULL) != NULL) == testfor;
2374       }
2375
2376     /* Test for a variable's having a non-empty value. A non-existent variable
2377     causes an expansion failure. */
2378
2379     else
2380       {
2381       if (!(t = find_variable(name, TRUE, yield == NULL, NULL)))
2382         {
2383         expand_string_message = (name[0] == 0)?
2384           string_sprintf("variable name omitted after \"def:\"") :
2385           string_sprintf("unknown variable \"%s\" after \"def:\"", name);
2386         check_variable_error_message(name);
2387         return NULL;
2388         }
2389       if (yield) *yield = (t[0] != 0) == testfor;
2390       }
2391
2392     return s;
2393     }
2394
2395
2396   /* first_delivery tests for first delivery attempt */
2397
2398   case ECOND_FIRST_DELIVERY:
2399   if (yield != NULL) *yield = f.deliver_firsttime == testfor;
2400   return s;
2401
2402
2403   /* queue_running tests for any process started by a queue runner */
2404
2405   case ECOND_QUEUE_RUNNING:
2406   if (yield != NULL) *yield = (queue_run_pid != (pid_t)0) == testfor;
2407   return s;
2408
2409
2410   /* exists:  tests for file existence
2411        isip:  tests for any IP address
2412       isip4:  tests for an IPv4 address
2413       isip6:  tests for an IPv6 address
2414         pam:  does PAM authentication
2415      radius:  does RADIUS authentication
2416    ldapauth:  does LDAP authentication
2417     pwcheck:  does Cyrus SASL pwcheck authentication
2418   */
2419
2420   case ECOND_EXISTS:
2421   case ECOND_ISIP:
2422   case ECOND_ISIP4:
2423   case ECOND_ISIP6:
2424   case ECOND_PAM:
2425   case ECOND_RADIUS:
2426   case ECOND_LDAPAUTH:
2427   case ECOND_PWCHECK:
2428
2429   while (isspace(*s)) s++;
2430   if (*s != '{') goto COND_FAILED_CURLY_START;          /* }-for-text-editors */
2431
2432   sub[0] = expand_string_internal(s+1, TRUE, &s, yield == NULL, TRUE, resetok);
2433   if (sub[0] == NULL) return NULL;
2434   /* {-for-text-editors */
2435   if (*s++ != '}') goto COND_FAILED_CURLY_END;
2436
2437   if (yield == NULL) return s;   /* No need to run the test if skipping */
2438
2439   switch(cond_type)
2440     {
2441     case ECOND_EXISTS:
2442     if ((expand_forbid & RDO_EXISTS) != 0)
2443       {
2444       expand_string_message = US"File existence tests are not permitted";
2445       return NULL;
2446       }
2447     *yield = (Ustat(sub[0], &statbuf) == 0) == testfor;
2448     break;
2449
2450     case ECOND_ISIP:
2451     case ECOND_ISIP4:
2452     case ECOND_ISIP6:
2453     rc = string_is_ip_address(sub[0], NULL);
2454     *yield = ((cond_type == ECOND_ISIP)? (rc != 0) :
2455              (cond_type == ECOND_ISIP4)? (rc == 4) : (rc == 6)) == testfor;
2456     break;
2457
2458     /* Various authentication tests - all optionally compiled */
2459
2460     case ECOND_PAM:
2461     #ifdef SUPPORT_PAM
2462     rc = auth_call_pam(sub[0], &expand_string_message);
2463     goto END_AUTH;
2464     #else
2465     goto COND_FAILED_NOT_COMPILED;
2466     #endif  /* SUPPORT_PAM */
2467
2468     case ECOND_RADIUS:
2469     #ifdef RADIUS_CONFIG_FILE
2470     rc = auth_call_radius(sub[0], &expand_string_message);
2471     goto END_AUTH;
2472     #else
2473     goto COND_FAILED_NOT_COMPILED;
2474     #endif  /* RADIUS_CONFIG_FILE */
2475
2476     case ECOND_LDAPAUTH:
2477     #ifdef LOOKUP_LDAP
2478       {
2479       /* Just to keep the interface the same */
2480       BOOL do_cache;
2481       int old_pool = store_pool;
2482       store_pool = POOL_SEARCH;
2483       rc = eldapauth_find((void *)(-1), NULL, sub[0], Ustrlen(sub[0]), NULL,
2484         &expand_string_message, &do_cache);
2485       store_pool = old_pool;
2486       }
2487     goto END_AUTH;
2488     #else
2489     goto COND_FAILED_NOT_COMPILED;
2490     #endif  /* LOOKUP_LDAP */
2491
2492     case ECOND_PWCHECK:
2493     #ifdef CYRUS_PWCHECK_SOCKET
2494     rc = auth_call_pwcheck(sub[0], &expand_string_message);
2495     goto END_AUTH;
2496     #else
2497     goto COND_FAILED_NOT_COMPILED;
2498     #endif  /* CYRUS_PWCHECK_SOCKET */
2499
2500     #if defined(SUPPORT_PAM) || defined(RADIUS_CONFIG_FILE) || \
2501         defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET)
2502     END_AUTH:
2503     if (rc == ERROR || rc == DEFER) return NULL;
2504     *yield = (rc == OK) == testfor;
2505     #endif
2506     }
2507   return s;
2508
2509
2510   /* call ACL (in a conditional context).  Accept true, deny false.
2511   Defer is a forced-fail.  Anything set by message= goes to $value.
2512   Up to ten parameters are used; we use the braces round the name+args
2513   like the saslauthd condition does, to permit a variable number of args.
2514   See also the expansion-item version EITEM_ACL and the traditional
2515   acl modifier ACLC_ACL.
2516   Since the ACL may allocate new global variables, tell our caller to not
2517   reclaim memory.
2518   */
2519
2520   case ECOND_ACL:
2521     /* ${if acl {{name}{arg1}{arg2}...}  {yes}{no}} */
2522     {
2523     uschar *sub[10];
2524     uschar *user_msg;
2525     BOOL cond = FALSE;
2526
2527     while (isspace(*s)) s++;
2528     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /*}*/
2529
2530     switch(read_subs(sub, nelem(sub), 1,
2531       &s, yield == NULL, TRUE, US"acl", resetok))
2532       {
2533       case 1: expand_string_message = US"too few arguments or bracketing "
2534         "error for acl";
2535       case 2:
2536       case 3: return NULL;
2537       }
2538
2539     if (yield != NULL)
2540       {
2541       int rc;
2542       *resetok = FALSE; /* eval_acl() might allocate; do not reclaim */
2543       switch(rc = eval_acl(sub, nelem(sub), &user_msg))
2544         {
2545         case OK:
2546           cond = TRUE;
2547         case FAIL:
2548           lookup_value = NULL;
2549           if (user_msg)
2550             lookup_value = string_copy(user_msg);
2551           *yield = cond == testfor;
2552           break;
2553
2554         case DEFER:
2555           f.expand_string_forcedfail = TRUE;
2556           /*FALLTHROUGH*/
2557         default:
2558           expand_string_message = string_sprintf("%s from acl \"%s\"",
2559             rc_names[rc], sub[0]);
2560           return NULL;
2561         }
2562       }
2563     return s;
2564     }
2565
2566
2567   /* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
2568
2569      ${if saslauthd {{username}{password}{service}{realm}}  {yes}{no}}
2570
2571   However, the last two are optional. That is why the whole set is enclosed
2572   in their own set of braces. */
2573
2574   case ECOND_SASLAUTHD:
2575 #ifndef CYRUS_SASLAUTHD_SOCKET
2576     goto COND_FAILED_NOT_COMPILED;
2577 #else
2578     {
2579     uschar *sub[4];
2580     while (isspace(*s)) s++;
2581     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
2582     switch(read_subs(sub, nelem(sub), 2, &s, yield == NULL, TRUE, US"saslauthd",
2583                     resetok))
2584       {
2585       case 1: expand_string_message = US"too few arguments or bracketing "
2586         "error for saslauthd";
2587       case 2:
2588       case 3: return NULL;
2589       }
2590     if (sub[2] == NULL) sub[3] = NULL;  /* realm if no service */
2591     if (yield != NULL)
2592       {
2593       int rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
2594         &expand_string_message);
2595       if (rc == ERROR || rc == DEFER) return NULL;
2596       *yield = (rc == OK) == testfor;
2597       }
2598     return s;
2599     }
2600 #endif /* CYRUS_SASLAUTHD_SOCKET */
2601
2602
2603   /* symbolic operators for numeric and string comparison, and a number of
2604   other operators, all requiring two arguments.
2605
2606   crypteq:           encrypts plaintext and compares against an encrypted text,
2607                        using crypt(), crypt16(), MD5 or SHA-1
2608   inlist/inlisti:    checks if first argument is in the list of the second
2609   match:             does a regular expression match and sets up the numerical
2610                        variables if it succeeds
2611   match_address:     matches in an address list
2612   match_domain:      matches in a domain list
2613   match_ip:          matches a host list that is restricted to IP addresses
2614   match_local_part:  matches in a local part list
2615   */
2616
2617   case ECOND_MATCH_ADDRESS:
2618   case ECOND_MATCH_DOMAIN:
2619   case ECOND_MATCH_IP:
2620   case ECOND_MATCH_LOCAL_PART:
2621 #ifndef EXPAND_LISTMATCH_RHS
2622     sub2_honour_dollar = FALSE;
2623 #endif
2624     /* FALLTHROUGH */
2625
2626   case ECOND_CRYPTEQ:
2627   case ECOND_INLIST:
2628   case ECOND_INLISTI:
2629   case ECOND_MATCH:
2630
2631   case ECOND_NUM_L:     /* Numerical comparisons */
2632   case ECOND_NUM_LE:
2633   case ECOND_NUM_E:
2634   case ECOND_NUM_EE:
2635   case ECOND_NUM_G:
2636   case ECOND_NUM_GE:
2637
2638   case ECOND_STR_LT:    /* String comparisons */
2639   case ECOND_STR_LTI:
2640   case ECOND_STR_LE:
2641   case ECOND_STR_LEI:
2642   case ECOND_STR_EQ:
2643   case ECOND_STR_EQI:
2644   case ECOND_STR_GT:
2645   case ECOND_STR_GTI:
2646   case ECOND_STR_GE:
2647   case ECOND_STR_GEI:
2648
2649   for (int i = 0; i < 2; i++)
2650     {
2651     /* Sometimes, we don't expand substrings; too many insecure configurations
2652     created using match_address{}{} and friends, where the second param
2653     includes information from untrustworthy sources. */
2654     BOOL honour_dollar = TRUE;
2655     if ((i > 0) && !sub2_honour_dollar)
2656       honour_dollar = FALSE;
2657
2658     while (isspace(*s)) s++;
2659     if (*s != '{')
2660       {
2661       if (i == 0) goto COND_FAILED_CURLY_START;
2662       expand_string_message = string_sprintf("missing 2nd string in {} "
2663         "after \"%s\"", opname);
2664       return NULL;
2665       }
2666     if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL,
2667         honour_dollar, resetok)))
2668       return NULL;
2669     DEBUG(D_expand) if (i == 1 && !sub2_honour_dollar && Ustrchr(sub[1], '$'))
2670       debug_printf_indent("WARNING: the second arg is NOT expanded,"
2671                         " for security reasons\n");
2672     if (*s++ != '}') goto COND_FAILED_CURLY_END;
2673
2674     /* Convert to numerical if required; we know that the names of all the
2675     conditions that compare numbers do not start with a letter. This just saves
2676     checking for them individually. */
2677
2678     if (!isalpha(opname[0]) && yield != NULL)
2679       if (sub[i][0] == 0)
2680         {
2681         num[i] = 0;
2682         DEBUG(D_expand)
2683           debug_printf_indent("empty string cast to zero for numerical comparison\n");
2684         }
2685       else
2686         {
2687         num[i] = expanded_string_integer(sub[i], FALSE);
2688         if (expand_string_message != NULL) return NULL;
2689         }
2690     }
2691
2692   /* Result not required */
2693
2694   if (yield == NULL) return s;
2695
2696   /* Do an appropriate comparison */
2697
2698   switch(cond_type)
2699     {
2700     case ECOND_NUM_E:
2701     case ECOND_NUM_EE:
2702     tempcond = (num[0] == num[1]);
2703     break;
2704
2705     case ECOND_NUM_G:
2706     tempcond = (num[0] > num[1]);
2707     break;
2708
2709     case ECOND_NUM_GE:
2710     tempcond = (num[0] >= num[1]);
2711     break;
2712
2713     case ECOND_NUM_L:
2714     tempcond = (num[0] < num[1]);
2715     break;
2716
2717     case ECOND_NUM_LE:
2718     tempcond = (num[0] <= num[1]);
2719     break;
2720
2721     case ECOND_STR_LT:
2722     tempcond = (Ustrcmp(sub[0], sub[1]) < 0);
2723     break;
2724
2725     case ECOND_STR_LTI:
2726     tempcond = (strcmpic(sub[0], sub[1]) < 0);
2727     break;
2728
2729     case ECOND_STR_LE:
2730     tempcond = (Ustrcmp(sub[0], sub[1]) <= 0);
2731     break;
2732
2733     case ECOND_STR_LEI:
2734     tempcond = (strcmpic(sub[0], sub[1]) <= 0);
2735     break;
2736
2737     case ECOND_STR_EQ:
2738     tempcond = (Ustrcmp(sub[0], sub[1]) == 0);
2739     break;
2740
2741     case ECOND_STR_EQI:
2742     tempcond = (strcmpic(sub[0], sub[1]) == 0);
2743     break;
2744
2745     case ECOND_STR_GT:
2746     tempcond = (Ustrcmp(sub[0], sub[1]) > 0);
2747     break;
2748
2749     case ECOND_STR_GTI:
2750     tempcond = (strcmpic(sub[0], sub[1]) > 0);
2751     break;
2752
2753     case ECOND_STR_GE:
2754     tempcond = (Ustrcmp(sub[0], sub[1]) >= 0);
2755     break;
2756
2757     case ECOND_STR_GEI:
2758     tempcond = (strcmpic(sub[0], sub[1]) >= 0);
2759     break;
2760
2761     case ECOND_MATCH:   /* Regular expression match */
2762     re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror, &roffset,
2763       NULL);
2764     if (re == NULL)
2765       {
2766       expand_string_message = string_sprintf("regular expression error in "
2767         "\"%s\": %s at offset %d", sub[1], rerror, roffset);
2768       return NULL;
2769       }
2770     tempcond = regex_match_and_setup(re, sub[0], 0, -1);
2771     break;
2772
2773     case ECOND_MATCH_ADDRESS:  /* Match in an address list */
2774     rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0, NULL);
2775     goto MATCHED_SOMETHING;
2776
2777     case ECOND_MATCH_DOMAIN:   /* Match in a domain list */
2778     rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
2779       MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
2780     goto MATCHED_SOMETHING;
2781
2782     case ECOND_MATCH_IP:       /* Match IP address in a host list */
2783     if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) == 0)
2784       {
2785       expand_string_message = string_sprintf("\"%s\" is not an IP address",
2786         sub[0]);
2787       return NULL;
2788       }
2789     else
2790       {
2791       unsigned int *nullcache = NULL;
2792       check_host_block cb;
2793
2794       cb.host_name = US"";
2795       cb.host_address = sub[0];
2796
2797       /* If the host address starts off ::ffff: it is an IPv6 address in
2798       IPv4-compatible mode. Find the IPv4 part for checking against IPv4
2799       addresses. */
2800
2801       cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
2802         cb.host_address + 7 : cb.host_address;
2803
2804       rc = match_check_list(
2805              &sub[1],                   /* the list */
2806              0,                         /* separator character */
2807              &hostlist_anchor,          /* anchor pointer */
2808              &nullcache,                /* cache pointer */
2809              check_host,                /* function for testing */
2810              &cb,                       /* argument for function */
2811              MCL_HOST,                  /* type of check */
2812              sub[0],                    /* text for debugging */
2813              NULL);                     /* where to pass back data */
2814       }
2815     goto MATCHED_SOMETHING;
2816
2817     case ECOND_MATCH_LOCAL_PART:
2818     rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
2819       MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
2820     /* Fall through */
2821     /* VVVVVVVVVVVV */
2822     MATCHED_SOMETHING:
2823     switch(rc)
2824       {
2825       case OK:
2826       tempcond = TRUE;
2827       break;
2828
2829       case FAIL:
2830       tempcond = FALSE;
2831       break;
2832
2833       case DEFER:
2834       expand_string_message = string_sprintf("unable to complete match "
2835         "against \"%s\": %s", sub[1], search_error_message);
2836       return NULL;
2837       }
2838
2839     break;
2840
2841     /* Various "encrypted" comparisons. If the second string starts with
2842     "{" then an encryption type is given. Default to crypt() or crypt16()
2843     (build-time choice). */
2844     /* }-for-text-editors */
2845
2846     case ECOND_CRYPTEQ:
2847     #ifndef SUPPORT_CRYPTEQ
2848     goto COND_FAILED_NOT_COMPILED;
2849     #else
2850     if (strncmpic(sub[1], US"{md5}", 5) == 0)
2851       {
2852       int sublen = Ustrlen(sub[1]+5);
2853       md5 base;
2854       uschar digest[16];
2855
2856       md5_start(&base);
2857       md5_end(&base, sub[0], Ustrlen(sub[0]), digest);
2858
2859       /* If the length that we are comparing against is 24, the MD5 digest
2860       is expressed as a base64 string. This is the way LDAP does it. However,
2861       some other software uses a straightforward hex representation. We assume
2862       this if the length is 32. Other lengths fail. */
2863
2864       if (sublen == 24)
2865         {
2866         uschar *coded = b64encode(CUS digest, 16);
2867         DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
2868           "  subject=%s\n  crypted=%s\n", coded, sub[1]+5);
2869         tempcond = (Ustrcmp(coded, sub[1]+5) == 0);
2870         }
2871       else if (sublen == 32)
2872         {
2873         uschar coded[36];
2874         for (int i = 0; i < 16; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
2875         coded[32] = 0;
2876         DEBUG(D_auth) debug_printf("crypteq: using MD5+hex hashing\n"
2877           "  subject=%s\n  crypted=%s\n", coded, sub[1]+5);
2878         tempcond = (strcmpic(coded, sub[1]+5) == 0);
2879         }
2880       else
2881         {
2882         DEBUG(D_auth) debug_printf("crypteq: length for MD5 not 24 or 32: "
2883           "fail\n  crypted=%s\n", sub[1]+5);
2884         tempcond = FALSE;
2885         }
2886       }
2887
2888     else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
2889       {
2890       int sublen = Ustrlen(sub[1]+6);
2891       hctx h;
2892       uschar digest[20];
2893
2894       sha1_start(&h);
2895       sha1_end(&h, sub[0], Ustrlen(sub[0]), digest);
2896
2897       /* If the length that we are comparing against is 28, assume the SHA1
2898       digest is expressed as a base64 string. If the length is 40, assume a
2899       straightforward hex representation. Other lengths fail. */
2900
2901       if (sublen == 28)
2902         {
2903         uschar *coded = b64encode(CUS digest, 20);
2904         DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
2905           "  subject=%s\n  crypted=%s\n", coded, sub[1]+6);
2906         tempcond = (Ustrcmp(coded, sub[1]+6) == 0);
2907         }
2908       else if (sublen == 40)
2909         {
2910         uschar coded[44];
2911         for (int i = 0; i < 20; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
2912         coded[40] = 0;
2913         DEBUG(D_auth) debug_printf("crypteq: using SHA1+hex hashing\n"
2914           "  subject=%s\n  crypted=%s\n", coded, sub[1]+6);
2915         tempcond = (strcmpic(coded, sub[1]+6) == 0);
2916         }
2917       else
2918         {
2919         DEBUG(D_auth) debug_printf("crypteq: length for SHA-1 not 28 or 40: "
2920           "fail\n  crypted=%s\n", sub[1]+6);
2921         tempcond = FALSE;
2922         }
2923       }
2924
2925     else   /* {crypt} or {crypt16} and non-{ at start */
2926            /* }-for-text-editors */
2927       {
2928       int which = 0;
2929       uschar *coded;
2930
2931       if (strncmpic(sub[1], US"{crypt}", 7) == 0)
2932         {
2933         sub[1] += 7;
2934         which = 1;
2935         }
2936       else if (strncmpic(sub[1], US"{crypt16}", 9) == 0)
2937         {
2938         sub[1] += 9;
2939         which = 2;
2940         }
2941       else if (sub[1][0] == '{')                /* }-for-text-editors */
2942         {
2943         expand_string_message = string_sprintf("unknown encryption mechanism "
2944           "in \"%s\"", sub[1]);
2945         return NULL;
2946         }
2947
2948       switch(which)
2949         {
2950         case 0:  coded = US DEFAULT_CRYPT(CS sub[0], CS sub[1]); break;
2951         case 1:  coded = US crypt(CS sub[0], CS sub[1]); break;
2952         default: coded = US crypt16(CS sub[0], CS sub[1]); break;
2953         }
2954
2955       #define STR(s) # s
2956       #define XSTR(s) STR(s)
2957       DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
2958         "  subject=%s\n  crypted=%s\n",
2959         which == 0 ? XSTR(DEFAULT_CRYPT) : which == 1 ? "crypt" : "crypt16",
2960         coded, sub[1]);
2961       #undef STR
2962       #undef XSTR
2963
2964       /* If the encrypted string contains fewer than two characters (for the
2965       salt), force failure. Otherwise we get false positives: with an empty
2966       string the yield of crypt() is an empty string! */
2967
2968       if (coded)
2969         tempcond = Ustrlen(sub[1]) < 2 ? FALSE : Ustrcmp(coded, sub[1]) == 0;
2970       else if (errno == EINVAL)
2971         tempcond = FALSE;
2972       else
2973         {
2974         expand_string_message = string_sprintf("crypt error: %s\n",
2975           US strerror(errno));
2976         return NULL;
2977         }
2978       }
2979     break;
2980     #endif  /* SUPPORT_CRYPTEQ */
2981
2982     case ECOND_INLIST:
2983     case ECOND_INLISTI:
2984       {
2985       const uschar * list = sub[1];
2986       int sep = 0;
2987       uschar *save_iterate_item = iterate_item;
2988       int (*compare)(const uschar *, const uschar *);
2989
2990       DEBUG(D_expand) debug_printf_indent("condition: %s  item: %s\n", opname, sub[0]);
2991
2992       tempcond = FALSE;
2993       compare = cond_type == ECOND_INLISTI
2994         ? strcmpic : (int (*)(const uschar *, const uschar *)) strcmp;
2995
2996       while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
2997         {
2998         DEBUG(D_expand) debug_printf_indent(" compare %s\n", iterate_item);
2999         if (compare(sub[0], iterate_item) == 0)
3000           {
3001           tempcond = TRUE;
3002           break;
3003           }
3004         }
3005       iterate_item = save_iterate_item;
3006       }
3007
3008     }   /* Switch for comparison conditions */
3009
3010   *yield = tempcond == testfor;
3011   return s;    /* End of comparison conditions */
3012
3013
3014   /* and/or: computes logical and/or of several conditions */
3015
3016   case ECOND_AND:
3017   case ECOND_OR:
3018   subcondptr = (yield == NULL)? NULL : &tempcond;
3019   combined_cond = (cond_type == ECOND_AND);
3020
3021   while (isspace(*s)) s++;
3022   if (*s++ != '{') goto COND_FAILED_CURLY_START;        /* }-for-text-editors */
3023
3024   for (;;)
3025     {
3026     while (isspace(*s)) s++;
3027     /* {-for-text-editors */
3028     if (*s == '}') break;
3029     if (*s != '{')                                      /* }-for-text-editors */
3030       {
3031       expand_string_message = string_sprintf("each subcondition "
3032         "inside an \"%s{...}\" condition must be in its own {}", opname);
3033       return NULL;
3034       }
3035
3036     if (!(s = eval_condition(s+1, resetok, subcondptr)))
3037       {
3038       expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
3039         expand_string_message, opname);
3040       return NULL;
3041       }
3042     while (isspace(*s)) s++;
3043
3044     /* {-for-text-editors */
3045     if (*s++ != '}')
3046       {
3047       /* {-for-text-editors */
3048       expand_string_message = string_sprintf("missing } at end of condition "
3049         "inside \"%s\" group", opname);
3050       return NULL;
3051       }
3052
3053     if (yield != NULL)
3054       {
3055       if (cond_type == ECOND_AND)
3056         {
3057         combined_cond &= tempcond;
3058         if (!combined_cond) subcondptr = NULL;  /* once false, don't */
3059         }                                       /* evaluate any more */
3060       else
3061         {
3062         combined_cond |= tempcond;
3063         if (combined_cond) subcondptr = NULL;   /* once true, don't */
3064         }                                       /* evaluate any more */
3065       }
3066     }
3067
3068   if (yield != NULL) *yield = (combined_cond == testfor);
3069   return ++s;
3070
3071
3072   /* forall/forany: iterates a condition with different values */
3073
3074   case ECOND_FORALL:      is_forany = FALSE;  is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3075   case ECOND_FORANY:      is_forany = TRUE;   is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3076   case ECOND_FORALL_JSON: is_forany = FALSE;  is_json = TRUE;  is_jsons = FALSE; goto FORMANY;
3077   case ECOND_FORANY_JSON: is_forany = TRUE;   is_json = TRUE;  is_jsons = FALSE; goto FORMANY;
3078   case ECOND_FORALL_JSONS: is_forany = FALSE; is_json = TRUE;  is_jsons = TRUE;  goto FORMANY;
3079   case ECOND_FORANY_JSONS: is_forany = TRUE;  is_json = TRUE;  is_jsons = TRUE;  goto FORMANY;
3080
3081   FORMANY:
3082     {
3083     const uschar * list;
3084     int sep = 0;
3085     uschar *save_iterate_item = iterate_item;
3086
3087     DEBUG(D_expand) debug_printf_indent("condition: %s\n", opname);
3088
3089     while (isspace(*s)) s++;
3090     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
3091     sub[0] = expand_string_internal(s, TRUE, &s, (yield == NULL), TRUE, resetok);
3092     if (sub[0] == NULL) return NULL;
3093     /* {-for-text-editors */
3094     if (*s++ != '}') goto COND_FAILED_CURLY_END;
3095
3096     while (isspace(*s)) s++;
3097     if (*s++ != '{') goto COND_FAILED_CURLY_START;      /* }-for-text-editors */
3098
3099     sub[1] = s;
3100
3101     /* Call eval_condition once, with result discarded (as if scanning a
3102     "false" part). This allows us to find the end of the condition, because if
3103     the list it empty, we won't actually evaluate the condition for real. */
3104
3105     if (!(s = eval_condition(sub[1], resetok, NULL)))
3106       {
3107       expand_string_message = string_sprintf("%s inside \"%s\" condition",
3108         expand_string_message, opname);
3109       return NULL;
3110       }
3111     while (isspace(*s)) s++;
3112
3113     /* {-for-text-editors */
3114     if (*s++ != '}')
3115       {
3116       /* {-for-text-editors */
3117       expand_string_message = string_sprintf("missing } at end of condition "
3118         "inside \"%s\"", opname);
3119       return NULL;
3120       }
3121
3122     if (yield) *yield = !testfor;
3123     list = sub[0];
3124     if (is_json) list = dewrap(string_copy(list), US"[]");
3125     while ((iterate_item = is_json
3126       ? json_nextinlist(&list) : string_nextinlist(&list, &sep, NULL, 0)))
3127       {
3128       if (is_jsons)
3129         if (!(iterate_item = dewrap(iterate_item, US"\"\"")))
3130           {
3131           expand_string_message =
3132             string_sprintf("%s wrapping string result for extract jsons",
3133               expand_string_message);
3134           iterate_item = save_iterate_item;
3135           return NULL;
3136           }
3137
3138       DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", name, iterate_item);
3139       if (!eval_condition(sub[1], resetok, &tempcond))
3140         {
3141         expand_string_message = string_sprintf("%s inside \"%s\" condition",
3142           expand_string_message, opname);
3143         iterate_item = save_iterate_item;
3144         return NULL;
3145         }
3146       DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", opname,
3147         tempcond? "true":"false");
3148
3149       if (yield) *yield = (tempcond == testfor);
3150       if (tempcond == is_forany) break;
3151       }
3152
3153     iterate_item = save_iterate_item;
3154     return s;
3155     }
3156
3157
3158   /* The bool{} expansion condition maps a string to boolean.
3159   The values supported should match those supported by the ACL condition
3160   (acl.c, ACLC_CONDITION) so that we keep to a minimum the different ideas
3161   of true/false.  Note that Router "condition" rules have a different
3162   interpretation, where general data can be used and only a few values
3163   map to FALSE.
3164   Note that readconf.c boolean matching, for boolean configuration options,
3165   only matches true/yes/false/no.
3166   The bool_lax{} condition matches the Router logic, which is much more
3167   liberal. */
3168   case ECOND_BOOL:
3169   case ECOND_BOOL_LAX:
3170     {
3171     uschar *sub_arg[1];
3172     uschar *t, *t2;
3173     uschar *ourname;
3174     size_t len;
3175     BOOL boolvalue = FALSE;
3176     while (isspace(*s)) s++;
3177     if (*s != '{') goto COND_FAILED_CURLY_START;        /* }-for-text-editors */
3178     ourname = cond_type == ECOND_BOOL_LAX ? US"bool_lax" : US"bool";
3179     switch(read_subs(sub_arg, 1, 1, &s, yield == NULL, FALSE, ourname, resetok))
3180       {
3181       case 1: expand_string_message = string_sprintf(
3182                   "too few arguments or bracketing error for %s",
3183                   ourname);
3184       /*FALLTHROUGH*/
3185       case 2:
3186       case 3: return NULL;
3187       }
3188     t = sub_arg[0];
3189     while (isspace(*t)) t++;
3190     len = Ustrlen(t);
3191     if (len)
3192       {
3193       /* trailing whitespace: seems like a good idea to ignore it too */
3194       t2 = t + len - 1;
3195       while (isspace(*t2)) t2--;
3196       if (t2 != (t + len))
3197         {
3198         *++t2 = '\0';
3199         len = t2 - t;
3200         }
3201       }
3202     DEBUG(D_expand)
3203       debug_printf_indent("considering %s: %s\n", ourname, len ? t : US"<empty>");
3204     /* logic for the lax case from expand_check_condition(), which also does
3205     expands, and the logic is both short and stable enough that there should
3206     be no maintenance burden from replicating it. */
3207     if (len == 0)
3208       boolvalue = FALSE;
3209     else if (*t == '-'
3210              ? Ustrspn(t+1, "0123456789") == len-1
3211              : Ustrspn(t,   "0123456789") == len)
3212       {
3213       boolvalue = (Uatoi(t) == 0) ? FALSE : TRUE;
3214       /* expand_check_condition only does a literal string "0" check */
3215       if ((cond_type == ECOND_BOOL_LAX) && (len > 1))
3216         boolvalue = TRUE;
3217       }
3218     else if (strcmpic(t, US"true") == 0 || strcmpic(t, US"yes") == 0)
3219       boolvalue = TRUE;
3220     else if (strcmpic(t, US"false") == 0 || strcmpic(t, US"no") == 0)
3221       boolvalue = FALSE;
3222     else if (cond_type == ECOND_BOOL_LAX)
3223       boolvalue = TRUE;
3224     else
3225       {
3226       expand_string_message = string_sprintf("unrecognised boolean "
3227        "value \"%s\"", t);
3228       return NULL;
3229       }
3230     DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", ourname,
3231         boolvalue? "true":"false");
3232     if (yield != NULL) *yield = (boolvalue == testfor);
3233     return s;
3234     }
3235
3236   /* Unknown condition */
3237
3238   default:
3239     if (!expand_string_message || !*expand_string_message)
3240       expand_string_message = string_sprintf("unknown condition \"%s\"", opname);
3241     return NULL;
3242   }   /* End switch on condition type */
3243
3244 /* Missing braces at start and end of data */
3245
3246 COND_FAILED_CURLY_START:
3247 expand_string_message = string_sprintf("missing { after \"%s\"", opname);
3248 return NULL;
3249
3250 COND_FAILED_CURLY_END:
3251 expand_string_message = string_sprintf("missing } at end of \"%s\" condition",
3252   opname);
3253 return NULL;
3254
3255 /* A condition requires code that is not compiled */
3256
3257 #if !defined(SUPPORT_PAM) || !defined(RADIUS_CONFIG_FILE) || \
3258     !defined(LOOKUP_LDAP) || !defined(CYRUS_PWCHECK_SOCKET) || \
3259     !defined(SUPPORT_CRYPTEQ) || !defined(CYRUS_SASLAUTHD_SOCKET)
3260 COND_FAILED_NOT_COMPILED:
3261 expand_string_message = string_sprintf("support for \"%s\" not compiled",
3262   opname);
3263 return NULL;
3264 #endif
3265 }
3266
3267
3268
3269
3270 /*************************************************
3271 *          Save numerical variables              *
3272 *************************************************/
3273
3274 /* This function is called from items such as "if" that want to preserve and
3275 restore the numbered variables.
3276
3277 Arguments:
3278   save_expand_string    points to an array of pointers to set
3279   save_expand_nlength   points to an array of ints for the lengths
3280
3281 Returns:                the value of expand max to save
3282 */
3283
3284 static int
3285 save_expand_strings(uschar **save_expand_nstring, int *save_expand_nlength)
3286 {
3287 for (int i = 0; i <= expand_nmax; i++)
3288   {
3289   save_expand_nstring[i] = expand_nstring[i];
3290   save_expand_nlength[i] = expand_nlength[i];
3291   }
3292 return expand_nmax;
3293 }
3294
3295
3296
3297 /*************************************************
3298 *           Restore numerical variables          *
3299 *************************************************/
3300
3301 /* This function restored saved values of numerical strings.
3302
3303 Arguments:
3304   save_expand_nmax      the number of strings to restore
3305   save_expand_string    points to an array of pointers
3306   save_expand_nlength   points to an array of ints
3307
3308 Returns:                nothing
3309 */
3310
3311 static void
3312 restore_expand_strings(int save_expand_nmax, uschar **save_expand_nstring,
3313   int *save_expand_nlength)
3314 {
3315 expand_nmax = save_expand_nmax;
3316 for (int i = 0; i <= expand_nmax; i++)
3317   {
3318   expand_nstring[i] = save_expand_nstring[i];
3319   expand_nlength[i] = save_expand_nlength[i];
3320   }
3321 }
3322
3323
3324
3325
3326
3327 /*************************************************
3328 *            Handle yes/no substrings            *
3329 *************************************************/
3330
3331 /* This function is used by ${if}, ${lookup} and ${extract} to handle the
3332 alternative substrings that depend on whether or not the condition was true,
3333 or the lookup or extraction succeeded. The substrings always have to be
3334 expanded, to check their syntax, but "skipping" is set when the result is not
3335 needed - this avoids unnecessary nested lookups.
3336
3337 Arguments:
3338   skipping       TRUE if we were skipping when this item was reached
3339   yes            TRUE if the first string is to be used, else use the second
3340   save_lookup    a value to put back into lookup_value before the 2nd expansion
3341   sptr           points to the input string pointer
3342   yieldptr       points to the output growable-string pointer
3343   type           "lookup", "if", "extract", "run", "env", "listextract" or
3344                  "certextract" for error message
3345   resetok        if not NULL, pointer to flag - write FALSE if unsafe to reset
3346                 the store.
3347
3348 Returns:         0 OK; lookup_value has been reset to save_lookup
3349                  1 expansion failed
3350                  2 expansion failed because of bracketing error
3351 */
3352
3353 static int
3354 process_yesno(BOOL skipping, BOOL yes, uschar *save_lookup, const uschar **sptr,
3355   gstring ** yieldptr, uschar *type, BOOL *resetok)
3356 {
3357 int rc = 0;
3358 const uschar *s = *sptr;    /* Local value */
3359 uschar *sub1, *sub2;
3360 const uschar * errwhere;
3361
3362 /* If there are no following strings, we substitute the contents of $value for
3363 lookups and for extractions in the success case. For the ${if item, the string
3364 "true" is substituted. In the fail case, nothing is substituted for all three
3365 items. */
3366
3367 while (isspace(*s)) s++;
3368 if (*s == '}')
3369   {
3370   if (type[0] == 'i')
3371     {
3372     if (yes && !skipping)
3373       *yieldptr = string_catn(*yieldptr, US"true", 4);
3374     }
3375   else
3376     {
3377     if (yes && lookup_value && !skipping)
3378       *yieldptr = string_cat(*yieldptr, lookup_value);
3379     lookup_value = save_lookup;
3380     }
3381   s++;
3382   goto RETURN;
3383   }
3384
3385 /* The first following string must be braced. */
3386
3387 if (*s++ != '{')
3388   {
3389   errwhere = US"'yes' part did not start with '{'";
3390   goto FAILED_CURLY;
3391   }
3392
3393 /* Expand the first substring. Forced failures are noticed only if we actually
3394 want this string. Set skipping in the call in the fail case (this will always
3395 be the case if we were already skipping). */
3396
3397 sub1 = expand_string_internal(s, TRUE, &s, !yes, TRUE, resetok);
3398 if (sub1 == NULL && (yes || !f.expand_string_forcedfail)) goto FAILED;
3399 f.expand_string_forcedfail = FALSE;
3400 if (*s++ != '}')
3401   {
3402   errwhere = US"'yes' part did not end with '}'";
3403   goto FAILED_CURLY;
3404   }
3405
3406 /* If we want the first string, add it to the output */
3407
3408 if (yes)
3409   *yieldptr = string_cat(*yieldptr, sub1);
3410
3411 /* If this is called from a lookup/env or a (cert)extract, we want to restore
3412 $value to what it was at the start of the item, so that it has this value
3413 during the second string expansion. For the call from "if" or "run" to this
3414 function, save_lookup is set to lookup_value, so that this statement does
3415 nothing. */
3416
3417 lookup_value = save_lookup;
3418
3419 /* There now follows either another substring, or "fail", or nothing. This
3420 time, forced failures are noticed only if we want the second string. We must
3421 set skipping in the nested call if we don't want this string, or if we were
3422 already skipping. */
3423
3424 while (isspace(*s)) s++;
3425 if (*s == '{')
3426   {
3427   sub2 = expand_string_internal(s+1, TRUE, &s, yes || skipping, TRUE, resetok);
3428   if (sub2 == NULL && (!yes || !f.expand_string_forcedfail)) goto FAILED;
3429   f.expand_string_forcedfail = FALSE;
3430   if (*s++ != '}')
3431     {
3432     errwhere = US"'no' part did not start with '{'";
3433     goto FAILED_CURLY;
3434     }
3435
3436   /* If we want the second string, add it to the output */
3437
3438   if (!yes)
3439     *yieldptr = string_cat(*yieldptr, sub2);
3440   }
3441
3442 /* If there is no second string, but the word "fail" is present when the use of
3443 the second string is wanted, set a flag indicating it was a forced failure
3444 rather than a syntactic error. Swallow the terminating } in case this is nested
3445 inside another lookup or if or extract. */
3446
3447 else if (*s != '}')
3448   {
3449   uschar name[256];
3450   /* deconst cast ok here as source is s anyway */
3451   s = US read_name(name, sizeof(name), s, US"_");
3452   if (Ustrcmp(name, "fail") == 0)
3453     {
3454     if (!yes && !skipping)
3455       {
3456       while (isspace(*s)) s++;
3457       if (*s++ != '}')
3458         {
3459         errwhere = US"did not close with '}' after forcedfail";
3460         goto FAILED_CURLY;
3461         }
3462       expand_string_message =
3463         string_sprintf("\"%s\" failed and \"fail\" requested", type);
3464       f.expand_string_forcedfail = TRUE;
3465       goto FAILED;
3466       }
3467     }
3468   else
3469     {
3470     expand_string_message =
3471       string_sprintf("syntax error in \"%s\" item - \"fail\" expected", type);
3472     goto FAILED;
3473     }
3474   }
3475
3476 /* All we have to do now is to check on the final closing brace. */
3477
3478 while (isspace(*s)) s++;
3479 if (*s++ != '}')
3480   {
3481   errwhere = US"did not close with '}'";
3482   goto FAILED_CURLY;
3483   }
3484
3485
3486 RETURN:
3487 /* Update the input pointer value before returning */
3488 *sptr = s;
3489 return rc;
3490
3491 FAILED_CURLY:
3492   /* Get here if there is a bracketing failure */
3493   expand_string_message = string_sprintf(
3494     "curly-bracket problem in conditional yes/no parsing: %s\n"
3495     " remaining string is '%s'", errwhere, --s);
3496   rc = 2;
3497   goto RETURN;
3498
3499 FAILED:
3500   /* Get here for other failures */
3501   rc = 1;
3502   goto RETURN;
3503 }
3504
3505
3506
3507
3508 /*************************************************
3509 *    Handle MD5 or SHA-1 computation for HMAC    *
3510 *************************************************/
3511
3512 /* These are some wrapping functions that enable the HMAC code to be a bit
3513 cleaner. A good compiler will spot the tail recursion.
3514
3515 Arguments:
3516   type         HMAC_MD5 or HMAC_SHA1
3517   remaining    are as for the cryptographic hash functions
3518
3519 Returns:       nothing
3520 */
3521
3522 static void
3523 chash_start(int type, void *base)
3524 {
3525 if (type == HMAC_MD5)
3526   md5_start((md5 *)base);
3527 else
3528   sha1_start((hctx *)base);
3529 }
3530
3531 static void
3532 chash_mid(int type, void *base, uschar *string)
3533 {
3534 if (type == HMAC_MD5)
3535   md5_mid((md5 *)base, string);
3536 else
3537   sha1_mid((hctx *)base, string);
3538 }
3539
3540 static void
3541 chash_end(int type, void *base, uschar *string, int length, uschar *digest)
3542 {
3543 if (type == HMAC_MD5)
3544   md5_end((md5 *)base, string, length, digest);
3545 else
3546   sha1_end((hctx *)base, string, length, digest);
3547 }
3548
3549
3550
3551
3552
3553 /********************************************************
3554 * prvs: Get last three digits of days since Jan 1, 1970 *
3555 ********************************************************/
3556
3557 /* This is needed to implement the "prvs" BATV reverse
3558    path signing scheme
3559
3560 Argument: integer "days" offset to add or substract to
3561           or from the current number of days.
3562
3563 Returns:  pointer to string containing the last three
3564           digits of the number of days since Jan 1, 1970,
3565           modified by the offset argument, NULL if there
3566           was an error in the conversion.
3567
3568 */
3569
3570 static uschar *
3571 prvs_daystamp(int day_offset)
3572 {
3573 uschar *days = store_get(32);                /* Need at least 24 for cases */
3574 (void)string_format(days, 32, TIME_T_FMT,    /* where TIME_T_FMT is %lld */
3575   (time(NULL) + day_offset*86400)/86400);
3576 return (Ustrlen(days) >= 3) ? &days[Ustrlen(days)-3] : US"100";
3577 }
3578
3579
3580
3581 /********************************************************
3582 *   prvs: perform HMAC-SHA1 computation of prvs bits    *
3583 ********************************************************/
3584
3585 /* This is needed to implement the "prvs" BATV reverse
3586    path signing scheme
3587
3588 Arguments:
3589   address RFC2821 Address to use
3590       key The key to use (must be less than 64 characters
3591           in size)
3592   key_num Single-digit key number to use. Defaults to
3593           '0' when NULL.
3594
3595 Returns:  pointer to string containing the first three
3596           bytes of the final hash in hex format, NULL if
3597           there was an error in the process.
3598 */
3599
3600 static uschar *
3601 prvs_hmac_sha1(uschar *address, uschar *key, uschar *key_num, uschar *daystamp)
3602 {
3603 gstring * hash_source;
3604 uschar * p;
3605 hctx h;
3606 uschar innerhash[20];
3607 uschar finalhash[20];
3608 uschar innerkey[64];
3609 uschar outerkey[64];
3610 uschar *finalhash_hex = store_get(40);
3611
3612 if (key_num == NULL)
3613   key_num = US"0";
3614
3615 if (Ustrlen(key) > 64)
3616   return NULL;
3617
3618 hash_source = string_catn(NULL, key_num, 1);
3619 hash_source = string_catn(hash_source, daystamp, 3);
3620 hash_source = string_cat(hash_source, address);
3621 (void) string_from_gstring(hash_source);
3622
3623 DEBUG(D_expand)
3624   debug_printf_indent("prvs: hash source is '%s'\n", hash_source->s);
3625
3626 memset(innerkey, 0x36, 64);
3627 memset(outerkey, 0x5c, 64);
3628
3629 for (int i = 0; i < Ustrlen(key); i++)
3630   {
3631   innerkey[i] ^= key[i];
3632   outerkey[i] ^= key[i];
3633   }
3634
3635 chash_start(HMAC_SHA1, &h);
3636 chash_mid(HMAC_SHA1, &h, innerkey);
3637 chash_end(HMAC_SHA1, &h, hash_source->s, hash_source->ptr, innerhash);
3638
3639 chash_start(HMAC_SHA1, &h);
3640 chash_mid(HMAC_SHA1, &h, outerkey);
3641 chash_end(HMAC_SHA1, &h, innerhash, 20, finalhash);
3642
3643 p = finalhash_hex;
3644 for (int i = 0; i < 3; i++)
3645   {
3646   *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
3647   *p++ = hex_digits[finalhash[i] & 0x0f];
3648   }
3649 *p = '\0';
3650
3651 return finalhash_hex;
3652 }
3653
3654
3655
3656
3657 /*************************************************
3658 *        Join a file onto the output string      *
3659 *************************************************/
3660
3661 /* This is used for readfile/readsock and after a run expansion.
3662 It joins the contents of a file onto the output string, globally replacing
3663 newlines with a given string (optionally).
3664
3665 Arguments:
3666   f            the FILE
3667   yield        pointer to the expandable string struct
3668   eol          newline replacement string, or NULL
3669
3670 Returns:       new pointer for expandable string, terminated if non-null
3671 */
3672
3673 static gstring *
3674 cat_file(FILE *f, gstring *yield, uschar *eol)
3675 {
3676 uschar buffer[1024];
3677
3678 while (Ufgets(buffer, sizeof(buffer), f))
3679   {
3680   int len = Ustrlen(buffer);
3681   if (eol && buffer[len-1] == '\n') len--;
3682   yield = string_catn(yield, buffer, len);
3683   if (eol && buffer[len])
3684     yield = string_cat(yield, eol);
3685   }
3686
3687 (void) string_from_gstring(yield);
3688 return yield;
3689 }
3690
3691
3692 #ifndef DISABLE_TLS
3693 static gstring *
3694 cat_file_tls(void * tls_ctx, gstring * yield, uschar * eol)
3695 {
3696 int rc;
3697 uschar buffer[1024];
3698
3699 /*XXX could we read direct into a pre-grown string? */
3700
3701 while ((rc = tls_read(tls_ctx, buffer, sizeof(buffer))) > 0)
3702   for (uschar * s = buffer; rc--; s++)
3703     yield = eol && *s == '\n'
3704       ? string_cat(yield, eol) : string_catn(yield, s, 1);
3705
3706 /* We assume that all errors, and any returns of zero bytes,
3707 are actually EOF. */
3708
3709 (void) string_from_gstring(yield);
3710 return yield;
3711 }
3712 #endif
3713
3714
3715 /*************************************************
3716 *          Evaluate numeric expression           *
3717 *************************************************/
3718
3719 /* This is a set of mutually recursive functions that evaluate an arithmetic
3720 expression involving + - * / % & | ^ ~ << >> and parentheses. The only one of
3721 these functions that is called from elsewhere is eval_expr, whose interface is:
3722
3723 Arguments:
3724   sptr        pointer to the pointer to the string - gets updated
3725   decimal     TRUE if numbers are to be assumed decimal
3726   error       pointer to where to put an error message - must be NULL on input
3727   endket      TRUE if ')' must terminate - FALSE for external call
3728
3729 Returns:      on success: the value of the expression, with *error still NULL
3730               on failure: an undefined value, with *error = a message
3731 */
3732
3733 static int_eximarith_t eval_op_or(uschar **, BOOL, uschar **);
3734
3735
3736 static int_eximarith_t
3737 eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket)
3738 {
3739 uschar *s = *sptr;
3740 int_eximarith_t x = eval_op_or(&s, decimal, error);
3741
3742 if (!*error)
3743   if (endket)
3744     if (*s != ')')
3745       *error = US"expecting closing parenthesis";
3746     else
3747       while (isspace(*(++s)));
3748   else if (*s)
3749     *error = US"expecting operator";
3750 *sptr = s;
3751 return x;
3752 }
3753
3754
3755 static int_eximarith_t
3756 eval_number(uschar **sptr, BOOL decimal, uschar **error)
3757 {
3758 int c;
3759 int_eximarith_t n;
3760 uschar *s = *sptr;
3761
3762 while (isspace(*s)) s++;
3763 if (isdigit((c = *s)))
3764   {
3765   int count;
3766   (void)sscanf(CS s, (decimal? SC_EXIM_DEC "%n" : SC_EXIM_ARITH "%n"), &n, &count);
3767   s += count;
3768   switch (tolower(*s))
3769     {
3770     default: break;
3771     case 'k': n *= 1024; s++; break;
3772     case 'm': n *= 1024*1024; s++; break;
3773     case 'g': n *= 1024*1024*1024; s++; break;
3774     }
3775   while (isspace (*s)) s++;
3776   }
3777 else if (c == '(')
3778   {
3779   s++;
3780   n = eval_expr(&s, decimal, error, 1);
3781   }
3782 else
3783   {
3784   *error = US"expecting number or opening parenthesis";
3785   n = 0;
3786   }
3787 *sptr = s;
3788 return n;
3789 }
3790
3791
3792 static int_eximarith_t
3793 eval_op_unary(uschar **sptr, BOOL decimal, uschar **error)
3794 {
3795 uschar *s = *sptr;
3796 int_eximarith_t x;
3797 while (isspace(*s)) s++;
3798 if (*s == '+' || *s == '-' || *s == '~')
3799   {
3800   int op = *s++;
3801   x = eval_op_unary(&s, decimal, error);
3802   if (op == '-') x = -x;
3803     else if (op == '~') x = ~x;
3804   }
3805 else
3806   x = eval_number(&s, decimal, error);
3807
3808 *sptr = s;
3809 return x;
3810 }
3811
3812
3813 static int_eximarith_t
3814 eval_op_mult(uschar **sptr, BOOL decimal, uschar **error)
3815 {
3816 uschar *s = *sptr;
3817 int_eximarith_t x = eval_op_unary(&s, decimal, error);
3818 if (*error == NULL)
3819   {
3820   while (*s == '*' || *s == '/' || *s == '%')
3821     {
3822     int op = *s++;
3823     int_eximarith_t y = eval_op_unary(&s, decimal, error);
3824     if (*error != NULL) break;
3825     /* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give
3826      * a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which
3827      * is a bug somewhere in [gcc 4.2.1, FreeBSD, amd64].  In fact, -N*-M where
3828      * -N*M is INT_MIN will yield INT_MIN.
3829      * Since we don't support floating point, this is somewhat simpler.
3830      * Ideally, we'd return an error, but since we overflow for all other
3831      * arithmetic, consistency suggests otherwise, but what's the correct value
3832      * to use?  There is none.
3833      * The C standard guarantees overflow for unsigned arithmetic but signed
3834      * overflow invokes undefined behaviour; in practice, this is overflow
3835      * except for converting INT_MIN to INT_MAX+1.  We also can't guarantee
3836      * that long/longlong larger than int are available, or we could just work
3837      * with larger types.  We should consider whether to guarantee 32bit eval
3838      * and 64-bit working variables, with errors returned.  For now ...
3839      * So, the only SIGFPEs occur with a non-shrinking div/mod, thus -1; we
3840      * can just let the other invalid results occur otherwise, as they have
3841      * until now.  For this one case, we can coerce.
3842      */
3843     if (y == -1 && x == EXIM_ARITH_MIN && op != '*')
3844       {
3845       DEBUG(D_expand)
3846         debug_printf("Integer exception dodging: " PR_EXIM_ARITH "%c-1 coerced to " PR_EXIM_ARITH "\n",
3847             EXIM_ARITH_MIN, op, EXIM_ARITH_MAX);
3848       x = EXIM_ARITH_MAX;
3849       continue;
3850       }
3851     if (op == '*')
3852       x *= y;
3853     else
3854       {
3855       if (y == 0)
3856         {
3857         *error = (op == '/') ? US"divide by zero" : US"modulo by zero";
3858         x = 0;
3859         break;
3860         }
3861       if (op == '/')
3862         x /= y;
3863       else
3864         x %= y;
3865       }
3866     }
3867   }
3868 *sptr = s;
3869 return x;
3870 }
3871
3872
3873 static int_eximarith_t
3874 eval_op_sum(uschar **sptr, BOOL decimal, uschar **error)
3875 {
3876 uschar *s = *sptr;
3877 int_eximarith_t x = eval_op_mult(&s, decimal, error);
3878 if (!*error)
3879   {
3880   while (*s == '+' || *s == '-')
3881     {
3882     int op = *s++;
3883     int_eximarith_t y = eval_op_mult(&s, decimal, error);
3884     if (*error) break;
3885     if (  (x >=   EXIM_ARITH_MAX/2  && x >=   EXIM_ARITH_MAX/2)
3886        || (x <= -(EXIM_ARITH_MAX/2) && y <= -(EXIM_ARITH_MAX/2)))
3887       {                 /* over-conservative check */
3888       *error = op == '+'
3889         ? US"overflow in sum" : US"overflow in difference";
3890       break;
3891       }
3892     if (op == '+') x += y; else x -= y;
3893     }
3894   }
3895 *sptr = s;
3896 return x;
3897 }
3898
3899
3900 static int_eximarith_t
3901 eval_op_shift(uschar **sptr, BOOL decimal, uschar **error)
3902 {
3903 uschar *s = *sptr;
3904 int_eximarith_t x = eval_op_sum(&s, decimal, error);
3905 if (*error == NULL)
3906   {
3907   while ((*s == '<' || *s == '>') && s[1] == s[0])
3908     {
3909     int_eximarith_t y;
3910     int op = *s++;
3911     s++;
3912     y = eval_op_sum(&s, decimal, error);
3913     if (*error != NULL) break;
3914     if (op == '<') x <<= y; else x >>= y;
3915     }
3916   }
3917 *sptr = s;
3918 return x;
3919 }
3920
3921
3922 static int_eximarith_t
3923 eval_op_and(uschar **sptr, BOOL decimal, uschar **error)
3924 {
3925 uschar *s = *sptr;
3926 int_eximarith_t x = eval_op_shift(&s, decimal, error);
3927 if (*error == NULL)
3928   {
3929   while (*s == '&')
3930     {
3931     int_eximarith_t y;
3932     s++;
3933     y = eval_op_shift(&s, decimal, error);
3934     if (*error != NULL) break;
3935     x &= y;
3936     }
3937   }
3938 *sptr = s;
3939 return x;
3940 }
3941
3942
3943 static int_eximarith_t
3944 eval_op_xor(uschar **sptr, BOOL decimal, uschar **error)
3945 {
3946 uschar *s = *sptr;
3947 int_eximarith_t x = eval_op_and(&s, decimal, error);
3948 if (*error == NULL)
3949   {
3950   while (*s == '^')
3951     {
3952     int_eximarith_t y;
3953     s++;
3954     y = eval_op_and(&s, decimal, error);
3955     if (*error != NULL) break;
3956     x ^= y;
3957     }
3958   }
3959 *sptr = s;
3960 return x;
3961 }
3962
3963
3964 static int_eximarith_t
3965 eval_op_or(uschar **sptr, BOOL decimal, uschar **error)
3966 {
3967 uschar *s = *sptr;
3968 int_eximarith_t x = eval_op_xor(&s, decimal, error);
3969 if (*error == NULL)
3970   {
3971   while (*s == '|')
3972     {
3973     int_eximarith_t y;
3974     s++;
3975     y = eval_op_xor(&s, decimal, error);
3976     if (*error != NULL) break;
3977     x |= y;
3978     }
3979   }
3980 *sptr = s;
3981 return x;
3982 }
3983
3984
3985
3986 /************************************************/
3987 /* Comparison operation for sort expansion.  We need to avoid
3988 re-expanding the fields being compared, so need a custom routine.
3989
3990 Arguments:
3991  cond_type              Comparison operator code
3992  leftarg, rightarg      Arguments for comparison
3993
3994 Return true iff (leftarg compare rightarg)
3995 */
3996
3997 static BOOL
3998 sortsbefore(int cond_type, BOOL alpha_cond,
3999   const uschar * leftarg, const uschar * rightarg)
4000 {
4001 int_eximarith_t l_num, r_num;
4002
4003 if (!alpha_cond)
4004   {
4005   l_num = expanded_string_integer(leftarg, FALSE);
4006   if (expand_string_message) return FALSE;
4007   r_num = expanded_string_integer(rightarg, FALSE);
4008   if (expand_string_message) return FALSE;
4009
4010   switch (cond_type)
4011     {
4012     case ECOND_NUM_G:   return l_num >  r_num;
4013     case ECOND_NUM_GE:  return l_num >= r_num;
4014     case ECOND_NUM_L:   return l_num <  r_num;
4015     case ECOND_NUM_LE:  return l_num <= r_num;
4016     default: break;
4017     }
4018   }
4019 else
4020   switch (cond_type)
4021     {
4022     case ECOND_STR_LT:  return Ustrcmp (leftarg, rightarg) <  0;
4023     case ECOND_STR_LTI: return strcmpic(leftarg, rightarg) <  0;
4024     case ECOND_STR_LE:  return Ustrcmp (leftarg, rightarg) <= 0;
4025     case ECOND_STR_LEI: return strcmpic(leftarg, rightarg) <= 0;
4026     case ECOND_STR_GT:  return Ustrcmp (leftarg, rightarg) >  0;
4027     case ECOND_STR_GTI: return strcmpic(leftarg, rightarg) >  0;
4028     case ECOND_STR_GE:  return Ustrcmp (leftarg, rightarg) >= 0;
4029     case ECOND_STR_GEI: return strcmpic(leftarg, rightarg) >= 0;
4030     default: break;
4031     }
4032 return FALSE;   /* should not happen */
4033 }
4034
4035
4036 /*************************************************
4037 *                 Expand string                  *
4038 *************************************************/
4039
4040 /* Returns either an unchanged string, or the expanded string in stacking pool
4041 store. Interpreted sequences are:
4042
4043    \...                    normal escaping rules
4044    $name                   substitutes the variable
4045    ${name}                 ditto
4046    ${op:string}            operates on the expanded string value
4047    ${item{arg1}{arg2}...}  expands the args and then does the business
4048                              some literal args are not enclosed in {}
4049
4050 There are now far too many operators and item types to make it worth listing
4051 them here in detail any more.
4052
4053 We use an internal routine recursively to handle embedded substrings. The
4054 external function follows. The yield is NULL if the expansion failed, and there
4055 are two cases: if something collapsed syntactically, or if "fail" was given
4056 as the action on a lookup failure. These can be distinguished by looking at the
4057 variable expand_string_forcedfail, which is TRUE in the latter case.
4058
4059 The skipping flag is set true when expanding a substring that isn't actually
4060 going to be used (after "if" or "lookup") and it prevents lookups from
4061 happening lower down.
4062
4063 Store usage: At start, a store block of the length of the input plus 64
4064 is obtained. This is expanded as necessary by string_cat(), which might have to
4065 get a new block, or might be able to expand the original. At the end of the
4066 function we can release any store above that portion of the yield block that
4067 was actually used. In many cases this will be optimal.
4068
4069 However: if the first item in the expansion is a variable name or header name,
4070 we reset the store before processing it; if the result is in fresh store, we
4071 use that without copying. This is helpful for expanding strings like
4072 $message_headers which can get very long.
4073
4074 There's a problem if a ${dlfunc item has side-effects that cause allocation,
4075 since resetting the store at the end of the expansion will free store that was
4076 allocated by the plugin code as well as the slop after the expanded string. So
4077 we skip any resets if ${dlfunc } has been used. The same applies for ${acl }
4078 and, given the acl condition, ${if }. This is an unfortunate consequence of
4079 string expansion becoming too powerful.
4080
4081 Arguments:
4082   string         the string to be expanded
4083   ket_ends       true if expansion is to stop at }
4084   left           if not NULL, a pointer to the first character after the
4085                  expansion is placed here (typically used with ket_ends)
4086   skipping       TRUE for recursive calls when the value isn't actually going
4087                  to be used (to allow for optimisation)
4088   honour_dollar  TRUE if $ is to be expanded,
4089                  FALSE if it's just another character
4090   resetok_p      if not NULL, pointer to flag - write FALSE if unsafe to reset
4091                  the store.
4092
4093 Returns:         NULL if expansion fails:
4094                    expand_string_forcedfail is set TRUE if failure was forced
4095                    expand_string_message contains a textual error message
4096                  a pointer to the expanded string on success
4097 */
4098
4099 static uschar *
4100 expand_string_internal(const uschar *string, BOOL ket_ends, const uschar **left,
4101   BOOL skipping, BOOL honour_dollar, BOOL *resetok_p)
4102 {
4103 gstring * yield = string_get(Ustrlen(string) + 64);
4104 int item_type;
4105 const uschar *s = string;
4106 uschar *save_expand_nstring[EXPAND_MAXN+1];
4107 int save_expand_nlength[EXPAND_MAXN+1];
4108 BOOL resetok = TRUE;
4109
4110 expand_level++;
4111 DEBUG(D_expand)
4112   DEBUG(D_noutf8)
4113     debug_printf_indent("/%s: %s\n",
4114       skipping ? "---scanning" : "considering", string);
4115   else
4116     debug_printf_indent(UTF8_DOWN_RIGHT "%s: %s\n",
4117       skipping
4118       ? UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ "scanning"
4119       : "considering",
4120       string);
4121
4122 f.expand_string_forcedfail = FALSE;
4123 expand_string_message = US"";
4124
4125 while (*s != 0)
4126   {
4127   uschar *value;
4128   uschar name[256];
4129
4130   /* \ escapes the next character, which must exist, or else
4131   the expansion fails. There's a special escape, \N, which causes
4132   copying of the subject verbatim up to the next \N. Otherwise,
4133   the escapes are the standard set. */
4134
4135   if (*s == '\\')
4136     {
4137     if (s[1] == 0)
4138       {
4139       expand_string_message = US"\\ at end of string";
4140       goto EXPAND_FAILED;
4141       }
4142
4143     if (s[1] == 'N')
4144       {
4145       const uschar * t = s + 2;
4146       for (s = t; *s != 0; s++) if (*s == '\\' && s[1] == 'N') break;
4147       yield = string_catn(yield, t, s - t);
4148       if (*s != 0) s += 2;
4149       }
4150
4151     else
4152       {
4153       uschar ch[1];
4154       ch[0] = string_interpret_escape(&s);
4155       s++;
4156       yield = string_catn(yield, ch, 1);
4157       }
4158
4159     continue;
4160     }
4161
4162   /*{*/
4163   /* Anything other than $ is just copied verbatim, unless we are
4164   looking for a terminating } character. */
4165
4166   /*{*/
4167   if (ket_ends && *s == '}') break;
4168
4169   if (*s != '$' || !honour_dollar)
4170     {
4171     yield = string_catn(yield, s++, 1);
4172     continue;
4173     }
4174
4175   /* No { after the $ - must be a plain name or a number for string
4176   match variable. There has to be a fudge for variables that are the
4177   names of header fields preceded by "$header_" because header field
4178   names can contain any printing characters except space and colon.
4179   For those that don't like typing this much, "$h_" is a synonym for
4180   "$header_". A non-existent header yields a NULL value; nothing is
4181   inserted. */  /*}*/
4182
4183   if (isalpha((*(++s))))
4184     {
4185     int len;
4186     int newsize = 0;
4187     gstring * g = NULL;
4188     uschar * t;
4189
4190     s = read_name(name, sizeof(name), s, US"_");
4191
4192     /* If this is the first thing to be expanded, release the pre-allocated
4193     buffer. */
4194
4195     if (!yield)
4196       g = store_get(sizeof(gstring));
4197     else if (yield->ptr == 0)
4198       {
4199       if (resetok) store_reset(yield);
4200       yield = NULL;
4201       g = store_get(sizeof(gstring));   /* alloc _before_ calling find_variable() */
4202       }
4203
4204     /* Header */
4205
4206     if (  ( *(t = name) == 'h'
4207           || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
4208           )
4209        && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
4210        )
4211       {
4212       unsigned flags = *name == 'r' ? FH_WANT_RAW
4213                       : *name == 'l' ? FH_WANT_RAW|FH_WANT_LIST
4214                       : 0;
4215       uschar * charset = *name == 'b' ? NULL : headers_charset;
4216
4217       s = read_header_name(name, sizeof(name), s);
4218       value = find_header(name, &newsize, flags, charset);
4219
4220       /* If we didn't find the header, and the header contains a closing brace
4221       character, this may be a user error where the terminating colon
4222       has been omitted. Set a flag to adjust the error message in this case.
4223       But there is no error here - nothing gets inserted. */
4224
4225       if (!value)
4226         {
4227         if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
4228         continue;
4229         }
4230       }
4231
4232     /* Variable */
4233
4234     else if (!(value = find_variable(name, FALSE, skipping, &newsize)))
4235       {
4236       expand_string_message =
4237         string_sprintf("unknown variable name \"%s\"", name);
4238         check_variable_error_message(name);
4239       goto EXPAND_FAILED;
4240       }
4241
4242     /* If the data is known to be in a new buffer, newsize will be set to the
4243     size of that buffer. If this is the first thing in an expansion string,
4244     yield will be NULL; just point it at the new store instead of copying. Many
4245     expansion strings contain just one reference, so this is a useful
4246     optimization, especially for humungous headers.  We need to use a gstring
4247     structure that is not allocated after that new-buffer, else a later store
4248     reset in the middle of the buffer will make it inaccessible. */
4249
4250     len = Ustrlen(value);
4251     if (!yield && newsize != 0)
4252       {
4253       yield = g;
4254       yield->size = newsize;
4255       yield->ptr = len;
4256       yield->s = value;
4257       }
4258     else
4259       yield = string_catn(yield, value, len);
4260
4261     continue;
4262     }
4263
4264   if (isdigit(*s))
4265     {
4266     int n;
4267     s = read_cnumber(&n, s);
4268     if (n >= 0 && n <= expand_nmax)
4269       yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
4270     continue;
4271     }
4272
4273   /* Otherwise, if there's no '{' after $ it's an error. */             /*}*/
4274
4275   if (*s != '{')                                                        /*}*/
4276     {
4277     expand_string_message = US"$ not followed by letter, digit, or {";  /*}*/
4278     goto EXPAND_FAILED;
4279     }
4280
4281   /* After { there can be various things, but they all start with
4282   an initial word, except for a number for a string match variable. */
4283
4284   if (isdigit((*(++s))))
4285     {
4286     int n;
4287     s = read_cnumber(&n, s);            /*{*/
4288     if (*s++ != '}')
4289       {                                 /*{*/
4290       expand_string_message = US"} expected after number";
4291       goto EXPAND_FAILED;
4292       }
4293     if (n >= 0 && n <= expand_nmax)
4294       yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
4295     continue;
4296     }
4297
4298   if (!isalpha(*s))
4299     {
4300     expand_string_message = US"letter or digit expected after ${";      /*}*/
4301     goto EXPAND_FAILED;
4302     }
4303
4304   /* Allow "-" in names to cater for substrings with negative
4305   arguments. Since we are checking for known names after { this is
4306   OK. */
4307
4308   s = read_name(name, sizeof(name), s, US"_-");
4309   item_type = chop_match(name, item_table, nelem(item_table));
4310
4311   switch(item_type)
4312     {
4313     /* Call an ACL from an expansion.  We feed data in via $acl_arg1 - $acl_arg9.
4314     If the ACL returns accept or reject we return content set by "message ="
4315     There is currently no limit on recursion; this would have us call
4316     acl_check_internal() directly and get a current level from somewhere.
4317     See also the acl expansion condition ECOND_ACL and the traditional
4318     acl modifier ACLC_ACL.
4319     Assume that the function has side-effects on the store that must be preserved.
4320     */
4321
4322     case EITEM_ACL:
4323       /* ${acl {name} {arg1}{arg2}...} */
4324       {
4325       uschar *sub[10];  /* name + arg1-arg9 (which must match number of acl_arg[]) */
4326       uschar *user_msg;
4327       int rc;
4328
4329       switch(read_subs(sub, nelem(sub), 1, &s, skipping, TRUE, US"acl",
4330                       &resetok))
4331         {
4332         case 1: goto EXPAND_FAILED_CURLY;
4333         case 2:
4334         case 3: goto EXPAND_FAILED;
4335         }
4336       if (skipping) continue;
4337
4338       resetok = FALSE;
4339       switch(rc = eval_acl(sub, nelem(sub), &user_msg))
4340         {
4341         case OK:
4342         case FAIL:
4343           DEBUG(D_expand)
4344             debug_printf_indent("acl expansion yield: %s\n", user_msg);
4345           if (user_msg)
4346             yield = string_cat(yield, user_msg);
4347           continue;
4348
4349         case DEFER:
4350           f.expand_string_forcedfail = TRUE;
4351           /*FALLTHROUGH*/
4352         default:
4353           expand_string_message = string_sprintf("%s from acl \"%s\"",
4354             rc_names[rc], sub[0]);
4355           goto EXPAND_FAILED;
4356         }
4357       }
4358
4359     case EITEM_AUTHRESULTS:
4360       /* ${authresults {mysystemname}} */
4361       {
4362       uschar *sub_arg[1];
4363
4364       switch(read_subs(sub_arg, nelem(sub_arg), 1, &s, skipping, TRUE, name,
4365                       &resetok))
4366         {
4367         case 1: goto EXPAND_FAILED_CURLY;
4368         case 2:
4369         case 3: goto EXPAND_FAILED;
4370         }
4371
4372       yield = string_append(yield, 3,
4373                         US"Authentication-Results: ", sub_arg[0], US"; none");
4374       yield->ptr -= 6;
4375
4376       yield = authres_local(yield, sub_arg[0]);
4377       yield = authres_iprev(yield);
4378       yield = authres_smtpauth(yield);
4379 #ifdef SUPPORT_SPF
4380       yield = authres_spf(yield);
4381 #endif
4382 #ifndef DISABLE_DKIM
4383       yield = authres_dkim(yield);
4384 #endif
4385 #ifdef EXPERIMENTAL_DMARC
4386       yield = authres_dmarc(yield);
4387 #endif
4388 #ifdef EXPERIMENTAL_ARC
4389       yield = authres_arc(yield);
4390 #endif
4391       continue;
4392       }
4393
4394     /* Handle conditionals - preserve the values of the numerical expansion
4395     variables in case they get changed by a regular expression match in the
4396     condition. If not, they retain their external settings. At the end
4397     of this "if" section, they get restored to their previous values. */
4398
4399     case EITEM_IF:
4400       {
4401       BOOL cond = FALSE;
4402       const uschar *next_s;
4403       int save_expand_nmax =
4404         save_expand_strings(save_expand_nstring, save_expand_nlength);
4405
4406       while (isspace(*s)) s++;
4407       next_s = eval_condition(s, &resetok, skipping ? NULL : &cond);
4408       if (next_s == NULL) goto EXPAND_FAILED;  /* message already set */
4409
4410       DEBUG(D_expand)
4411         DEBUG(D_noutf8)
4412           {
4413           debug_printf_indent("|--condition: %.*s\n", (int)(next_s - s), s);
4414           debug_printf_indent("|-----result: %s\n", cond ? "true" : "false");
4415           }
4416         else
4417           {
4418           debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
4419             "condition: %.*s\n",
4420             (int)(next_s - s), s);
4421           debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
4422             UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
4423             "result: %s\n",
4424             cond ? "true" : "false");
4425           }
4426
4427       s = next_s;
4428
4429       /* The handling of "yes" and "no" result strings is now in a separate
4430       function that is also used by ${lookup} and ${extract} and ${run}. */
4431
4432       switch(process_yesno(
4433                skipping,                     /* were previously skipping */
4434                cond,                         /* success/failure indicator */
4435                lookup_value,                 /* value to reset for string2 */
4436                &s,                           /* input pointer */
4437                &yield,                       /* output pointer */
4438                US"if",                       /* condition type */
4439                &resetok))
4440         {
4441         case 1: goto EXPAND_FAILED;          /* when all is well, the */
4442         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
4443         }
4444
4445       /* Restore external setting of expansion variables for continuation
4446       at this level. */
4447
4448       restore_expand_strings(save_expand_nmax, save_expand_nstring,
4449         save_expand_nlength);
4450       continue;
4451       }
4452
4453 #ifdef SUPPORT_I18N
4454     case EITEM_IMAPFOLDER:
4455       {                         /* ${imapfolder {name}{sep]{specials}} */
4456       uschar *sub_arg[3];
4457       uschar *encoded;
4458
4459       switch(read_subs(sub_arg, nelem(sub_arg), 1, &s, skipping, TRUE, name,
4460                       &resetok))
4461         {
4462         case 1: goto EXPAND_FAILED_CURLY;
4463         case 2:
4464         case 3: goto EXPAND_FAILED;
4465         }
4466
4467       if (sub_arg[1] == NULL)           /* One argument */
4468         {
4469         sub_arg[1] = US"/";             /* default separator */
4470         sub_arg[2] = NULL;
4471         }
4472       else if (Ustrlen(sub_arg[1]) != 1)
4473         {
4474         expand_string_message =
4475           string_sprintf(
4476                 "IMAP folder separator must be one character, found \"%s\"",
4477                 sub_arg[1]);
4478         goto EXPAND_FAILED;
4479         }
4480
4481       if (!skipping)
4482         {
4483         if (!(encoded = imap_utf7_encode(sub_arg[0], headers_charset,
4484                             sub_arg[1][0], sub_arg[2], &expand_string_message)))
4485           goto EXPAND_FAILED;
4486         yield = string_cat(yield, encoded);
4487         }
4488       continue;
4489       }
4490 #endif
4491
4492     /* Handle database lookups unless locked out. If "skipping" is TRUE, we are
4493     expanding an internal string that isn't actually going to be used. All we
4494     need to do is check the syntax, so don't do a lookup at all. Preserve the
4495     values of the numerical expansion variables in case they get changed by a
4496     partial lookup. If not, they retain their external settings. At the end
4497     of this "lookup" section, they get restored to their previous values. */
4498
4499     case EITEM_LOOKUP:
4500       {
4501       int stype, partial, affixlen, starflags;
4502       int expand_setup = 0;
4503       int nameptr = 0;
4504       uschar *key, *filename;
4505       const uschar *affix;
4506       uschar *save_lookup_value = lookup_value;
4507       int save_expand_nmax =
4508         save_expand_strings(save_expand_nstring, save_expand_nlength);
4509
4510       if ((expand_forbid & RDO_LOOKUP) != 0)
4511         {
4512         expand_string_message = US"lookup expansions are not permitted";
4513         goto EXPAND_FAILED;
4514         }
4515
4516       /* Get the key we are to look up for single-key+file style lookups.
4517       Otherwise set the key NULL pro-tem. */
4518
4519       while (isspace(*s)) s++;
4520       if (*s == '{')                                    /*}*/
4521         {
4522         key = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
4523         if (!key) goto EXPAND_FAILED;                   /*{{*/
4524         if (*s++ != '}')
4525           {
4526           expand_string_message = US"missing '}' after lookup key";
4527           goto EXPAND_FAILED_CURLY;
4528           }
4529         while (isspace(*s)) s++;
4530         }
4531       else key = NULL;
4532
4533       /* Find out the type of database */
4534
4535       if (!isalpha(*s))
4536         {
4537         expand_string_message = US"missing lookup type";
4538         goto EXPAND_FAILED;
4539         }
4540
4541       /* The type is a string that may contain special characters of various
4542       kinds. Allow everything except space or { to appear; the actual content
4543       is checked by search_findtype_partial. */         /*}*/
4544
4545       while (*s != 0 && *s != '{' && !isspace(*s))      /*}*/
4546         {
4547         if (nameptr < sizeof(name) - 1) name[nameptr++] = *s;
4548         s++;
4549         }
4550       name[nameptr] = 0;
4551       while (isspace(*s)) s++;
4552
4553       /* Now check for the individual search type and any partial or default
4554       options. Only those types that are actually in the binary are valid. */
4555
4556       stype = search_findtype_partial(name, &partial, &affix, &affixlen,
4557         &starflags);
4558       if (stype < 0)
4559         {
4560         expand_string_message = search_error_message;
4561         goto EXPAND_FAILED;
4562         }
4563
4564       /* Check that a key was provided for those lookup types that need it,
4565       and was not supplied for those that use the query style. */
4566
4567       if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery))
4568         {
4569         if (key == NULL)
4570           {
4571           expand_string_message = string_sprintf("missing {key} for single-"
4572             "key \"%s\" lookup", name);
4573           goto EXPAND_FAILED;
4574           }
4575         }
4576       else
4577         {
4578         if (key != NULL)
4579           {
4580           expand_string_message = string_sprintf("a single key was given for "
4581             "lookup type \"%s\", which is not a single-key lookup type", name);
4582           goto EXPAND_FAILED;
4583           }
4584         }
4585
4586       /* Get the next string in brackets and expand it. It is the file name for
4587       single-key+file lookups, and the whole query otherwise. In the case of
4588       queries that also require a file name (e.g. sqlite), the file name comes
4589       first. */
4590
4591       if (*s != '{')
4592         {
4593         expand_string_message = US"missing '{' for lookup file-or-query arg";
4594         goto EXPAND_FAILED_CURLY;
4595         }
4596       filename = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
4597       if (filename == NULL) goto EXPAND_FAILED;
4598       if (*s++ != '}')
4599         {
4600         expand_string_message = US"missing '}' closing lookup file-or-query arg";
4601         goto EXPAND_FAILED_CURLY;
4602         }
4603       while (isspace(*s)) s++;
4604
4605       /* If this isn't a single-key+file lookup, re-arrange the variables
4606       to be appropriate for the search_ functions. For query-style lookups,
4607       there is just a "key", and no file name. For the special query-style +
4608       file types, the query (i.e. "key") starts with a file name. */
4609
4610       if (!key)
4611         {
4612         while (isspace(*filename)) filename++;
4613         key = filename;
4614
4615         if (mac_islookup(stype, lookup_querystyle))
4616           filename = NULL;
4617         else
4618           {
4619           if (*filename != '/')
4620             {
4621             expand_string_message = string_sprintf(
4622               "absolute file name expected for \"%s\" lookup", name);
4623             goto EXPAND_FAILED;
4624             }
4625           while (*key != 0 && !isspace(*key)) key++;
4626           if (*key != 0) *key++ = 0;
4627           }
4628         }
4629
4630       /* If skipping, don't do the next bit - just lookup_value == NULL, as if
4631       the entry was not found. Note that there is no search_close() function.
4632       Files are left open in case of re-use. At suitable places in higher logic,
4633       search_tidyup() is called to tidy all open files. This can save opening
4634       the same file several times. However, files may also get closed when
4635       others are opened, if too many are open at once. The rule is that a
4636       handle should not be used after a second search_open().
4637
4638       Request that a partial search sets up $1 and maybe $2 by passing
4639       expand_setup containing zero. If its value changes, reset expand_nmax,
4640       since new variables will have been set. Note that at the end of this
4641       "lookup" section, the old numeric variables are restored. */
4642
4643       if (skipping)
4644         lookup_value = NULL;
4645       else
4646         {
4647         void *handle = search_open(filename, stype, 0, NULL, NULL);
4648         if (handle == NULL)
4649           {
4650           expand_string_message = search_error_message;
4651           goto EXPAND_FAILED;
4652           }
4653         lookup_value = search_find(handle, filename, key, partial, affix,
4654           affixlen, starflags, &expand_setup);
4655         if (f.search_find_defer)
4656           {
4657           expand_string_message =
4658             string_sprintf("lookup of \"%s\" gave DEFER: %s",
4659               string_printing2(key, FALSE), search_error_message);
4660           goto EXPAND_FAILED;
4661           }
4662         if (expand_setup > 0) expand_nmax = expand_setup;
4663         }
4664
4665       /* The handling of "yes" and "no" result strings is now in a separate
4666       function that is also used by ${if} and ${extract}. */
4667
4668       switch(process_yesno(
4669                skipping,                     /* were previously skipping */
4670                lookup_value != NULL,         /* success/failure indicator */
4671                save_lookup_value,            /* value to reset for string2 */
4672                &s,                           /* input pointer */
4673                &yield,                       /* output pointer */
4674                US"lookup",                   /* condition type */
4675                &resetok))
4676         {
4677         case 1: goto EXPAND_FAILED;          /* when all is well, the */
4678         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
4679         }
4680
4681       /* Restore external setting of expansion variables for carrying on
4682       at this level, and continue. */
4683
4684       restore_expand_strings(save_expand_nmax, save_expand_nstring,
4685         save_expand_nlength);
4686       continue;
4687       }
4688
4689     /* If Perl support is configured, handle calling embedded perl subroutines,
4690     unless locked out at this time. Syntax is ${perl{sub}} or ${perl{sub}{arg}}
4691     or ${perl{sub}{arg1}{arg2}} or up to a maximum of EXIM_PERL_MAX_ARGS
4692     arguments (defined below). */
4693
4694     #define EXIM_PERL_MAX_ARGS 8
4695
4696     case EITEM_PERL:
4697     #ifndef EXIM_PERL
4698     expand_string_message = US"\"${perl\" encountered, but this facility "      /*}*/
4699       "is not included in this binary";
4700     goto EXPAND_FAILED;
4701
4702     #else   /* EXIM_PERL */
4703       {
4704       uschar *sub_arg[EXIM_PERL_MAX_ARGS + 2];
4705       gstring *new_yield;
4706
4707       if ((expand_forbid & RDO_PERL) != 0)
4708         {
4709         expand_string_message = US"Perl calls are not permitted";
4710         goto EXPAND_FAILED;
4711         }
4712
4713       switch(read_subs(sub_arg, EXIM_PERL_MAX_ARGS + 1, 1, &s, skipping, TRUE,
4714            US"perl", &resetok))
4715         {
4716         case 1: goto EXPAND_FAILED_CURLY;
4717         case 2:
4718         case 3: goto EXPAND_FAILED;
4719         }
4720
4721       /* If skipping, we don't actually do anything */
4722
4723       if (skipping) continue;
4724
4725       /* Start the interpreter if necessary */
4726
4727       if (!opt_perl_started)
4728         {
4729         uschar *initerror;
4730         if (opt_perl_startup == NULL)
4731           {
4732           expand_string_message = US"A setting of perl_startup is needed when "
4733             "using the Perl interpreter";
4734           goto EXPAND_FAILED;
4735           }
4736         DEBUG(D_any) debug_printf("Starting Perl interpreter\n");
4737         initerror = init_perl(opt_perl_startup);
4738         if (initerror != NULL)
4739           {
4740           expand_string_message =
4741             string_sprintf("error in perl_startup code: %s\n", initerror);
4742           goto EXPAND_FAILED;
4743           }
4744         opt_perl_started = TRUE;
4745         }
4746
4747       /* Call the function */
4748
4749       sub_arg[EXIM_PERL_MAX_ARGS + 1] = NULL;
4750       new_yield = call_perl_cat(yield, &expand_string_message,
4751         sub_arg[0], sub_arg + 1);
4752
4753       /* NULL yield indicates failure; if the message pointer has been set to
4754       NULL, the yield was undef, indicating a forced failure. Otherwise the
4755       message will indicate some kind of Perl error. */
4756
4757       if (new_yield == NULL)
4758         {
4759         if (expand_string_message == NULL)
4760           {
4761           expand_string_message =
4762             string_sprintf("Perl subroutine \"%s\" returned undef to force "
4763               "failure", sub_arg[0]);
4764           f.expand_string_forcedfail = TRUE;
4765           }
4766         goto EXPAND_FAILED;
4767         }
4768
4769       /* Yield succeeded. Ensure forcedfail is unset, just in case it got
4770       set during a callback from Perl. */
4771
4772       f.expand_string_forcedfail = FALSE;
4773       yield = new_yield;
4774       continue;
4775       }
4776     #endif /* EXIM_PERL */
4777
4778     /* Transform email address to "prvs" scheme to use
4779        as BATV-signed return path */
4780
4781     case EITEM_PRVS:
4782       {
4783       uschar *sub_arg[3];
4784       uschar *p,*domain;
4785
4786       switch(read_subs(sub_arg, 3, 2, &s, skipping, TRUE, US"prvs", &resetok))
4787         {
4788         case 1: goto EXPAND_FAILED_CURLY;
4789         case 2:
4790         case 3: goto EXPAND_FAILED;
4791         }
4792
4793       /* If skipping, we don't actually do anything */
4794       if (skipping) continue;
4795
4796       /* sub_arg[0] is the address */
4797       if (  !(domain = Ustrrchr(sub_arg[0],'@'))
4798          || domain == sub_arg[0] || Ustrlen(domain) == 1)
4799         {
4800         expand_string_message = US"prvs first argument must be a qualified email address";
4801         goto EXPAND_FAILED;
4802         }
4803
4804       /* Calculate the hash. The third argument must be a single-digit
4805       key number, or unset. */
4806
4807       if (  sub_arg[2]
4808          && (!isdigit(sub_arg[2][0]) || sub_arg[2][1] != 0))
4809         {
4810         expand_string_message = US"prvs third argument must be a single digit";
4811         goto EXPAND_FAILED;
4812         }
4813
4814       p = prvs_hmac_sha1(sub_arg[0], sub_arg[1], sub_arg[2], prvs_daystamp(7));
4815       if (!p)
4816         {
4817         expand_string_message = US"prvs hmac-sha1 conversion failed";
4818         goto EXPAND_FAILED;
4819         }
4820
4821       /* Now separate the domain from the local part */
4822       *domain++ = '\0';
4823
4824       yield = string_catn(yield, US"prvs=", 5);
4825       yield = string_catn(yield, sub_arg[2] ? sub_arg[2] : US"0", 1);
4826       yield = string_catn(yield, prvs_daystamp(7), 3);
4827       yield = string_catn(yield, p, 6);
4828       yield = string_catn(yield, US"=", 1);
4829       yield = string_cat (yield, sub_arg[0]);
4830       yield = string_catn(yield, US"@", 1);
4831       yield = string_cat (yield, domain);
4832
4833       continue;
4834       }
4835
4836     /* Check a prvs-encoded address for validity */
4837
4838     case EITEM_PRVSCHECK:
4839       {
4840       uschar *sub_arg[3];
4841       gstring * g;
4842       const pcre *re;
4843       uschar *p;
4844
4845       /* TF: Ugliness: We want to expand parameter 1 first, then set
4846          up expansion variables that are used in the expansion of
4847          parameter 2. So we clone the string for the first
4848          expansion, where we only expand parameter 1.
4849
4850          PH: Actually, that isn't necessary. The read_subs() function is
4851          designed to work this way for the ${if and ${lookup expansions. I've
4852          tidied the code.
4853       */
4854
4855       /* Reset expansion variables */
4856       prvscheck_result = NULL;
4857       prvscheck_address = NULL;
4858       prvscheck_keynum = NULL;
4859
4860       switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, US"prvs", &resetok))
4861         {
4862         case 1: goto EXPAND_FAILED_CURLY;
4863         case 2:
4864         case 3: goto EXPAND_FAILED;
4865         }
4866
4867       re = regex_must_compile(US"^prvs\\=([0-9])([0-9]{3})([A-F0-9]{6})\\=(.+)\\@(.+)$",
4868                               TRUE,FALSE);
4869
4870       if (regex_match_and_setup(re,sub_arg[0],0,-1))
4871         {
4872         uschar *local_part = string_copyn(expand_nstring[4],expand_nlength[4]);
4873         uschar *key_num = string_copyn(expand_nstring[1],expand_nlength[1]);
4874         uschar *daystamp = string_copyn(expand_nstring[2],expand_nlength[2]);
4875         uschar *hash = string_copyn(expand_nstring[3],expand_nlength[3]);
4876         uschar *domain = string_copyn(expand_nstring[5],expand_nlength[5]);
4877
4878         DEBUG(D_expand) debug_printf_indent("prvscheck localpart: %s\n", local_part);
4879         DEBUG(D_expand) debug_printf_indent("prvscheck key number: %s\n", key_num);
4880         DEBUG(D_expand) debug_printf_indent("prvscheck daystamp: %s\n", daystamp);
4881         DEBUG(D_expand) debug_printf_indent("prvscheck hash: %s\n", hash);
4882         DEBUG(D_expand) debug_printf_indent("prvscheck domain: %s\n", domain);
4883
4884         /* Set up expansion variables */
4885         g = string_cat (NULL, local_part);
4886         g = string_catn(g, US"@", 1);
4887         g = string_cat (g, domain);
4888         prvscheck_address = string_from_gstring(g);
4889         prvscheck_keynum = string_copy(key_num);
4890
4891         /* Now expand the second argument */
4892         switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, US"prvs", &resetok))
4893           {
4894           case 1: goto EXPAND_FAILED_CURLY;
4895           case 2:
4896           case 3: goto EXPAND_FAILED;
4897           }
4898
4899         /* Now we have the key and can check the address. */
4900
4901         p = prvs_hmac_sha1(prvscheck_address, sub_arg[0], prvscheck_keynum,
4902           daystamp);
4903
4904         if (!p)
4905           {
4906           expand_string_message = US"hmac-sha1 conversion failed";
4907           goto EXPAND_FAILED;
4908           }
4909
4910         DEBUG(D_expand) debug_printf_indent("prvscheck: received hash is %s\n", hash);
4911         DEBUG(D_expand) debug_printf_indent("prvscheck:      own hash is %s\n", p);
4912
4913         if (Ustrcmp(p,hash) == 0)
4914           {
4915           /* Success, valid BATV address. Now check the expiry date. */
4916           uschar *now = prvs_daystamp(0);
4917           unsigned int inow = 0,iexpire = 1;
4918
4919           (void)sscanf(CS now,"%u",&inow);
4920           (void)sscanf(CS daystamp,"%u",&iexpire);
4921
4922           /* When "iexpire" is < 7, a "flip" has occurred.
4923              Adjust "inow" accordingly. */
4924           if ( (iexpire < 7) && (inow >= 993) ) inow = 0;
4925
4926           if (iexpire >= inow)
4927             {
4928             prvscheck_result = US"1";
4929             DEBUG(D_expand) debug_printf_indent("prvscheck: success, $pvrs_result set to 1\n");
4930             }
4931           else
4932             {
4933             prvscheck_result = NULL;
4934             DEBUG(D_expand) debug_printf_indent("prvscheck: signature expired, $pvrs_result unset\n");
4935             }
4936           }
4937         else
4938           {
4939           prvscheck_result = NULL;
4940           DEBUG(D_expand) debug_printf_indent("prvscheck: hash failure, $pvrs_result unset\n");
4941           }
4942
4943         /* Now expand the final argument. We leave this till now so that
4944         it can include $prvscheck_result. */
4945
4946         switch(read_subs(sub_arg, 1, 0, &s, skipping, TRUE, US"prvs", &resetok))
4947           {
4948           case 1: goto EXPAND_FAILED_CURLY;
4949           case 2:
4950           case 3: goto EXPAND_FAILED;
4951           }
4952
4953         yield = string_cat(yield,
4954           !sub_arg[0] || !*sub_arg[0] ? prvscheck_address : sub_arg[0]);
4955
4956         /* Reset the "internal" variables afterwards, because they are in
4957         dynamic store that will be reclaimed if the expansion succeeded. */
4958
4959         prvscheck_address = NULL;
4960         prvscheck_keynum = NULL;
4961         }
4962       else
4963         /* Does not look like a prvs encoded address, return the empty string.
4964            We need to make sure all subs are expanded first, so as to skip over
4965            the entire item. */
4966
4967         switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, US"prvs", &resetok))
4968           {
4969           case 1: goto EXPAND_FAILED_CURLY;
4970           case 2:
4971           case 3: goto EXPAND_FAILED;
4972           }
4973
4974       continue;
4975       }
4976
4977     /* Handle "readfile" to insert an entire file */
4978
4979     case EITEM_READFILE:
4980       {
4981       FILE *f;
4982       uschar *sub_arg[2];
4983
4984       if ((expand_forbid & RDO_READFILE) != 0)
4985         {
4986         expand_string_message = US"file insertions are not permitted";
4987         goto EXPAND_FAILED;
4988         }
4989
4990       switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, US"readfile", &resetok))
4991         {
4992         case 1: goto EXPAND_FAILED_CURLY;
4993         case 2:
4994         case 3: goto EXPAND_FAILED;
4995         }
4996
4997       /* If skipping, we don't actually do anything */
4998
4999       if (skipping) continue;
5000
5001       /* Open the file and read it */
5002
5003       if (!(f = Ufopen(sub_arg[0], "rb")))
5004         {
5005         expand_string_message = string_open_failed(errno, "%s", sub_arg[0]);
5006         goto EXPAND_FAILED;
5007         }
5008
5009       yield = cat_file(f, yield, sub_arg[1]);
5010       (void)fclose(f);
5011       continue;
5012       }
5013
5014     /* Handle "readsocket" to insert data from a socket, either
5015     Inet or Unix domain */
5016
5017     case EITEM_READSOCK:
5018       {
5019       client_conn_ctx cctx;
5020       int timeout = 5;
5021       int save_ptr = yield->ptr;
5022       FILE * fp = NULL;
5023       uschar * arg;
5024       uschar * sub_arg[4];
5025       uschar * server_name = NULL;
5026       host_item host;
5027       BOOL do_shutdown = TRUE;
5028       BOOL do_tls = FALSE;      /* Only set under ! DISABLE_TLS */
5029       blob reqstr;
5030
5031       if (expand_forbid & RDO_READSOCK)
5032         {
5033         expand_string_message = US"socket insertions are not permitted";
5034         goto EXPAND_FAILED;
5035         }
5036
5037       /* Read up to 4 arguments, but don't do the end of item check afterwards,
5038       because there may be a string for expansion on failure. */
5039
5040       switch(read_subs(sub_arg, 4, 2, &s, skipping, FALSE, US"readsocket", &resetok))
5041         {
5042         case 1: goto EXPAND_FAILED_CURLY;
5043         case 2:                             /* Won't occur: no end check */
5044         case 3: goto EXPAND_FAILED;
5045         }
5046
5047       /* Grab the request string, if any */
5048
5049       reqstr.data = sub_arg[1];
5050       reqstr.len = Ustrlen(sub_arg[1]);
5051
5052       /* Sort out timeout, if given.  The second arg is a list with the first element
5053       being a time value.  Any more are options of form "name=value".  Currently the
5054       only option recognised is "shutdown". */
5055
5056       if (sub_arg[2])
5057         {
5058         const uschar * list = sub_arg[2];
5059         uschar * item;
5060         int sep = 0;
5061
5062         item = string_nextinlist(&list, &sep, NULL, 0);
5063         if ((timeout = readconf_readtime(item, 0, FALSE)) < 0)
5064           {
5065           expand_string_message = string_sprintf("bad time value %s", item);
5066           goto EXPAND_FAILED;
5067           }
5068
5069         while ((item = string_nextinlist(&list, &sep, NULL, 0)))
5070           if (Ustrncmp(item, US"shutdown=", 9) == 0)
5071             { if (Ustrcmp(item + 9, US"no") == 0) do_shutdown = FALSE; }
5072 #ifndef DISABLE_TLS
5073           else if (Ustrncmp(item, US"tls=", 4) == 0)
5074             { if (Ustrcmp(item + 9, US"no") != 0) do_tls = TRUE; }
5075 #endif
5076         }
5077       else
5078         sub_arg[3] = NULL;                     /* No eol if no timeout */
5079
5080       /* If skipping, we don't actually do anything. Otherwise, arrange to
5081       connect to either an IP or a Unix socket. */
5082
5083       if (!skipping)
5084         {
5085         /* Handle an IP (internet) domain */
5086
5087         if (Ustrncmp(sub_arg[0], "inet:", 5) == 0)
5088           {
5089           int port;
5090           uschar * port_name;
5091
5092           server_name = sub_arg[0] + 5;
5093           port_name = Ustrrchr(server_name, ':');
5094
5095           /* Sort out the port */
5096
5097           if (!port_name)
5098             {
5099             expand_string_message =
5100               string_sprintf("missing port for readsocket %s", sub_arg[0]);
5101             goto EXPAND_FAILED;
5102             }
5103           *port_name++ = 0;           /* Terminate server name */
5104
5105           if (isdigit(*port_name))
5106             {
5107             uschar *end;
5108             port = Ustrtol(port_name, &end, 0);
5109             if (end != port_name + Ustrlen(port_name))
5110               {
5111               expand_string_message =
5112                 string_sprintf("invalid port number %s", port_name);
5113               goto EXPAND_FAILED;
5114               }
5115             }
5116           else
5117             {
5118             struct servent *service_info = getservbyname(CS port_name, "tcp");
5119             if (!service_info)
5120               {
5121               expand_string_message = string_sprintf("unknown port \"%s\"",
5122                 port_name);
5123               goto EXPAND_FAILED;
5124               }
5125             port = ntohs(service_info->s_port);
5126             }
5127
5128           /*XXX we trust that the request is idempotent for TFO.  Hmm. */
5129           cctx.sock = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
5130                   timeout, &host, &expand_string_message,
5131                   do_tls ? NULL : &reqstr);
5132           callout_address = NULL;
5133           if (cctx.sock < 0)
5134             goto SOCK_FAIL;
5135           if (!do_tls)
5136             reqstr.len = 0;
5137           }
5138
5139         /* Handle a Unix domain socket */
5140
5141         else
5142           {
5143           struct sockaddr_un sockun;         /* don't call this "sun" ! */
5144           int rc;
5145
5146           if ((cctx.sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
5147             {
5148             expand_string_message = string_sprintf("failed to create socket: %s",
5149               strerror(errno));
5150             goto SOCK_FAIL;
5151             }
5152
5153           sockun.sun_family = AF_UNIX;
5154           sprintf(sockun.sun_path, "%.*s", (int)(sizeof(sockun.sun_path)-1),
5155             sub_arg[0]);
5156           server_name = US sockun.sun_path;
5157
5158           sigalrm_seen = FALSE;
5159           ALARM(timeout);
5160           rc = connect(cctx.sock, (struct sockaddr *)(&sockun), sizeof(sockun));
5161           ALARM_CLR(0);
5162           if (sigalrm_seen)
5163             {
5164             expand_string_message = US "socket connect timed out";
5165             goto SOCK_FAIL;
5166             }
5167           if (rc < 0)
5168             {
5169             expand_string_message = string_sprintf("failed to connect to socket "
5170               "%s: %s", sub_arg[0], strerror(errno));
5171             goto SOCK_FAIL;
5172             }
5173           host.name = server_name;
5174           host.address = US"";
5175           }
5176
5177         DEBUG(D_expand) debug_printf_indent("connected to socket %s\n", sub_arg[0]);
5178
5179 #ifndef DISABLE_TLS
5180         if (do_tls)
5181           {
5182           smtp_connect_args conn_args = {.host = &host };
5183           tls_support tls_dummy = {.sni=NULL};
5184           uschar * errstr;
5185
5186           if (!tls_client_start(&cctx, &conn_args, NULL, &tls_dummy, &errstr))
5187             {
5188             expand_string_message = string_sprintf("TLS connect failed: %s", errstr);
5189             goto SOCK_FAIL;
5190             }
5191           }
5192 #endif
5193
5194         /* Allow sequencing of test actions */
5195         if (f.running_in_test_harness) millisleep(100);
5196
5197         /* Write the request string, if not empty or already done */
5198
5199         if (reqstr.len)
5200           {
5201           DEBUG(D_expand) debug_printf_indent("writing \"%s\" to socket\n",
5202             reqstr.data);
5203           if ( (
5204 #ifndef DISABLE_TLS
5205               do_tls ? tls_write(cctx.tls_ctx, reqstr.data, reqstr.len, FALSE) :
5206 #endif
5207                         write(cctx.sock, reqstr.data, reqstr.len)) != reqstr.len)
5208             {
5209             expand_string_message = string_sprintf("request write to socket "
5210               "failed: %s", strerror(errno));
5211             goto SOCK_FAIL;
5212             }
5213           }
5214
5215         /* Shut down the sending side of the socket. This helps some servers to
5216         recognise that it is their turn to do some work. Just in case some
5217         system doesn't have this function, make it conditional. */
5218
5219 #ifdef SHUT_WR
5220         if (!do_tls && do_shutdown) shutdown(cctx.sock, SHUT_WR);
5221 #endif
5222
5223         if (f.running_in_test_harness) millisleep(100);
5224
5225         /* Now we need to read from the socket, under a timeout. The function
5226         that reads a file can be used. */
5227
5228         if (!do_tls)
5229           fp = fdopen(cctx.sock, "rb");
5230         sigalrm_seen = FALSE;
5231         ALARM(timeout);
5232         yield =
5233 #ifndef DISABLE_TLS
5234           do_tls ? cat_file_tls(cctx.tls_ctx, yield, sub_arg[3]) :
5235 #endif
5236                     cat_file(fp, yield, sub_arg[3]);
5237         ALARM_CLR(0);
5238
5239 #ifndef DISABLE_TLS
5240         if (do_tls)
5241           {
5242           tls_close(cctx.tls_ctx, TRUE);
5243           close(cctx.sock);
5244           }
5245         else
5246 #endif
5247           (void)fclose(fp);
5248
5249         /* After a timeout, we restore the pointer in the result, that is,
5250         make sure we add nothing from the socket. */
5251
5252         if (sigalrm_seen)
5253           {
5254           yield->ptr = save_ptr;
5255           expand_string_message = US "socket read timed out";
5256           goto SOCK_FAIL;
5257           }
5258         }
5259
5260       /* The whole thing has worked (or we were skipping). If there is a
5261       failure string following, we need to skip it. */
5262
5263       if (*s == '{')
5264         {
5265         if (expand_string_internal(s+1, TRUE, &s, TRUE, TRUE, &resetok) == NULL)
5266           goto EXPAND_FAILED;
5267         if (*s++ != '}')
5268           {
5269           expand_string_message = US"missing '}' closing failstring for readsocket";
5270           goto EXPAND_FAILED_CURLY;
5271           }
5272         while (isspace(*s)) s++;
5273         }
5274
5275     READSOCK_DONE:
5276       if (*s++ != '}')
5277         {
5278         expand_string_message = US"missing '}' closing readsocket";
5279         goto EXPAND_FAILED_CURLY;
5280         }
5281       continue;
5282
5283       /* Come here on failure to create socket, connect socket, write to the
5284       socket, or timeout on reading. If another substring follows, expand and
5285       use it. Otherwise, those conditions give expand errors. */
5286
5287     SOCK_FAIL:
5288       if (*s != '{') goto EXPAND_FAILED;
5289       DEBUG(D_any) debug_printf("%s\n", expand_string_message);
5290       if (!(arg = expand_string_internal(s+1, TRUE, &s, FALSE, TRUE, &resetok)))
5291         goto EXPAND_FAILED;
5292       yield = string_cat(yield, arg);
5293       if (*s++ != '}')
5294         {
5295         expand_string_message = US"missing '}' closing failstring for readsocket";
5296         goto EXPAND_FAILED_CURLY;
5297         }
5298       while (isspace(*s)) s++;
5299       goto READSOCK_DONE;
5300       }
5301
5302     /* Handle "run" to execute a program. */
5303
5304     case EITEM_RUN:
5305       {
5306       FILE *f;
5307       uschar *arg;
5308       const uschar **argv;
5309       pid_t pid;
5310       int fd_in, fd_out;
5311
5312       if ((expand_forbid & RDO_RUN) != 0)
5313         {
5314         expand_string_message = US"running a command is not permitted";
5315         goto EXPAND_FAILED;
5316         }
5317
5318       while (isspace(*s)) s++;
5319       if (*s != '{')
5320         {
5321         expand_string_message = US"missing '{' for command arg of run";
5322         goto EXPAND_FAILED_CURLY;
5323         }
5324       arg = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
5325       if (arg == NULL) goto EXPAND_FAILED;
5326       while (isspace(*s)) s++;
5327       if (*s++ != '}')
5328         {
5329         expand_string_message = US"missing '}' closing command arg of run";
5330         goto EXPAND_FAILED_CURLY;
5331         }
5332
5333       if (skipping)   /* Just pretend it worked when we're skipping */
5334         {
5335         runrc = 0;
5336         lookup_value = NULL;
5337         }
5338       else
5339         {
5340         if (!transport_set_up_command(&argv,    /* anchor for arg list */
5341             arg,                                /* raw command */
5342             FALSE,                              /* don't expand the arguments */
5343             0,                                  /* not relevant when... */
5344             NULL,                               /* no transporting address */
5345             US"${run} expansion",               /* for error messages */
5346             &expand_string_message))            /* where to put error message */
5347           goto EXPAND_FAILED;
5348
5349         /* Create the child process, making it a group leader. */
5350
5351         if ((pid = child_open(USS argv, NULL, 0077, &fd_in, &fd_out, TRUE)) < 0)
5352           {
5353           expand_string_message =
5354             string_sprintf("couldn't create child process: %s", strerror(errno));
5355           goto EXPAND_FAILED;
5356           }
5357
5358         /* Nothing is written to the standard input. */
5359
5360         (void)close(fd_in);
5361
5362         /* Read the pipe to get the command's output into $value (which is kept
5363         in lookup_value). Read during execution, so that if the output exceeds
5364         the OS pipe buffer limit, we don't block forever. Remember to not release
5365         memory just allocated for $value. */
5366
5367         resetok = FALSE;
5368         f = fdopen(fd_out, "rb");
5369         sigalrm_seen = FALSE;
5370         ALARM(60);
5371         lookup_value = string_from_gstring(cat_file(f, NULL, NULL));
5372         ALARM_CLR(0);
5373         (void)fclose(f);
5374
5375         /* Wait for the process to finish, applying the timeout, and inspect its
5376         return code for serious disasters. Simple non-zero returns are passed on.
5377         */
5378
5379         if (sigalrm_seen || (runrc = child_close(pid, 30)) < 0)
5380           {
5381           if (sigalrm_seen || runrc == -256)
5382             {
5383             expand_string_message = string_sprintf("command timed out");
5384             killpg(pid, SIGKILL);       /* Kill the whole process group */
5385             }
5386
5387           else if (runrc == -257)
5388             expand_string_message = string_sprintf("wait() failed: %s",
5389               strerror(errno));
5390
5391           else
5392             expand_string_message = string_sprintf("command killed by signal %d",
5393               -runrc);
5394
5395           goto EXPAND_FAILED;
5396           }
5397         }
5398
5399       /* Process the yes/no strings; $value may be useful in both cases */
5400
5401       switch(process_yesno(
5402                skipping,                     /* were previously skipping */
5403                runrc == 0,                   /* success/failure indicator */
5404                lookup_value,                 /* value to reset for string2 */
5405                &s,                           /* input pointer */
5406                &yield,                       /* output pointer */
5407                US"run",                      /* condition type */
5408                &resetok))
5409         {
5410         case 1: goto EXPAND_FAILED;          /* when all is well, the */
5411         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
5412         }
5413
5414       continue;
5415       }
5416
5417     /* Handle character translation for "tr" */
5418
5419     case EITEM_TR:
5420       {
5421       int oldptr = yield->ptr;
5422       int o2m;
5423       uschar *sub[3];
5424
5425       switch(read_subs(sub, 3, 3, &s, skipping, TRUE, US"tr", &resetok))
5426         {
5427         case 1: goto EXPAND_FAILED_CURLY;
5428         case 2:
5429         case 3: goto EXPAND_FAILED;
5430         }
5431
5432       yield = string_cat(yield, sub[0]);
5433       o2m = Ustrlen(sub[2]) - 1;
5434
5435       if (o2m >= 0) for (; oldptr < yield->ptr; oldptr++)
5436         {
5437         uschar *m = Ustrrchr(sub[1], yield->s[oldptr]);
5438         if (m != NULL)
5439           {
5440           int o = m - sub[1];
5441           yield->s[oldptr] = sub[2][(o < o2m)? o : o2m];
5442           }
5443         }
5444
5445       continue;
5446       }
5447
5448     /* Handle "hash", "length", "nhash", and "substr" when they are given with
5449     expanded arguments. */
5450
5451     case EITEM_HASH:
5452     case EITEM_LENGTH:
5453     case EITEM_NHASH:
5454     case EITEM_SUBSTR:
5455       {
5456       int len;
5457       uschar *ret;
5458       int val[2] = { 0, -1 };
5459       uschar *sub[3];
5460
5461       /* "length" takes only 2 arguments whereas the others take 2 or 3.
5462       Ensure that sub[2] is set in the ${length } case. */
5463
5464       sub[2] = NULL;
5465       switch(read_subs(sub, (item_type == EITEM_LENGTH)? 2:3, 2, &s, skipping,
5466              TRUE, name, &resetok))
5467         {
5468         case 1: goto EXPAND_FAILED_CURLY;
5469         case 2:
5470         case 3: goto EXPAND_FAILED;
5471         }
5472
5473       /* Juggle the arguments if there are only two of them: always move the
5474       string to the last position and make ${length{n}{str}} equivalent to
5475       ${substr{0}{n}{str}}. See the defaults for val[] above. */
5476
5477       if (sub[2] == NULL)
5478         {
5479         sub[2] = sub[1];
5480         sub[1] = NULL;
5481         if (item_type == EITEM_LENGTH)
5482           {
5483           sub[1] = sub[0];
5484           sub[0] = NULL;
5485           }
5486         }
5487
5488       for (int i = 0; i < 2; i++) if (sub[i])
5489         {
5490         val[i] = (int)Ustrtol(sub[i], &ret, 10);
5491         if (*ret != 0 || (i != 0 && val[i] < 0))
5492           {
5493           expand_string_message = string_sprintf("\"%s\" is not a%s number "
5494             "(in \"%s\" expansion)", sub[i], (i != 0)? " positive" : "", name);
5495           goto EXPAND_FAILED;
5496           }
5497         }
5498
5499       ret =
5500         (item_type == EITEM_HASH)?
5501           compute_hash(sub[2], val[0], val[1], &len) :
5502         (item_type == EITEM_NHASH)?
5503           compute_nhash(sub[2], val[0], val[1], &len) :
5504           extract_substr(sub[2], val[0], val[1], &len);
5505
5506       if (ret == NULL) goto EXPAND_FAILED;
5507       yield = string_catn(yield, ret, len);
5508       continue;
5509       }
5510
5511     /* Handle HMAC computation: ${hmac{<algorithm>}{<secret>}{<text>}}
5512     This code originally contributed by Steve Haslam. It currently supports
5513     the use of MD5 and SHA-1 hashes.
5514
5515     We need some workspace that is large enough to handle all the supported
5516     hash types. Use macros to set the sizes rather than be too elaborate. */
5517
5518     #define MAX_HASHLEN      20
5519     #define MAX_HASHBLOCKLEN 64
5520
5521     case EITEM_HMAC:
5522       {
5523       uschar *sub[3];
5524       md5 md5_base;
5525       hctx sha1_ctx;
5526       void *use_base;
5527       int type;
5528       int hashlen;      /* Number of octets for the hash algorithm's output */
5529       int hashblocklen; /* Number of octets the hash algorithm processes */
5530       uschar *keyptr, *p;
5531       unsigned int keylen;
5532
5533       uschar keyhash[MAX_HASHLEN];
5534       uschar innerhash[MAX_HASHLEN];
5535       uschar finalhash[MAX_HASHLEN];
5536       uschar finalhash_hex[2*MAX_HASHLEN];
5537       uschar innerkey[MAX_HASHBLOCKLEN];
5538       uschar outerkey[MAX_HASHBLOCKLEN];
5539
5540       switch (read_subs(sub, 3, 3, &s, skipping, TRUE, name, &resetok))
5541         {
5542         case 1: goto EXPAND_FAILED_CURLY;
5543         case 2:
5544         case 3: goto EXPAND_FAILED;
5545         }
5546
5547       if (!skipping)
5548         {
5549         if (Ustrcmp(sub[0], "md5") == 0)
5550           {
5551           type = HMAC_MD5;
5552           use_base = &md5_base;
5553           hashlen = 16;
5554           hashblocklen = 64;
5555           }
5556         else if (Ustrcmp(sub[0], "sha1") == 0)
5557           {
5558           type = HMAC_SHA1;
5559           use_base = &sha1_ctx;
5560           hashlen = 20;
5561           hashblocklen = 64;
5562           }
5563         else
5564           {
5565           expand_string_message =
5566             string_sprintf("hmac algorithm \"%s\" is not recognised", sub[0]);
5567           goto EXPAND_FAILED;
5568           }
5569
5570         keyptr = sub[1];
5571         keylen = Ustrlen(keyptr);
5572
5573         /* If the key is longer than the hash block length, then hash the key
5574         first */
5575
5576         if (keylen > hashblocklen)
5577           {
5578           chash_start(type, use_base);
5579           chash_end(type, use_base, keyptr, keylen, keyhash);
5580           keyptr = keyhash;
5581           keylen = hashlen;
5582           }
5583
5584         /* Now make the inner and outer key values */
5585
5586         memset(innerkey, 0x36, hashblocklen);
5587         memset(outerkey, 0x5c, hashblocklen);
5588
5589         for (int i = 0; i < keylen; i++)
5590           {
5591           innerkey[i] ^= keyptr[i];
5592           outerkey[i] ^= keyptr[i];
5593           }
5594
5595         /* Now do the hashes */
5596
5597         chash_start(type, use_base);
5598         chash_mid(type, use_base, innerkey);
5599         chash_end(type, use_base, sub[2], Ustrlen(sub[2]), innerhash);
5600
5601         chash_start(type, use_base);
5602         chash_mid(type, use_base, outerkey);
5603         chash_end(type, use_base, innerhash, hashlen, finalhash);
5604
5605         /* Encode the final hash as a hex string */
5606
5607         p = finalhash_hex;
5608         for (int i = 0; i < hashlen; i++)
5609           {
5610           *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
5611           *p++ = hex_digits[finalhash[i] & 0x0f];
5612           }
5613
5614         DEBUG(D_any) debug_printf("HMAC[%s](%.*s,%s)=%.*s\n",
5615           sub[0], (int)keylen, keyptr, sub[2], hashlen*2, finalhash_hex);
5616
5617         yield = string_catn(yield, finalhash_hex, hashlen*2);
5618         }
5619       continue;
5620       }
5621
5622     /* Handle global substitution for "sg" - like Perl's s/xxx/yyy/g operator.
5623     We have to save the numerical variables and restore them afterwards. */
5624
5625     case EITEM_SG:
5626       {
5627       const pcre *re;
5628       int moffset, moffsetextra, slen;
5629       int roffset;
5630       int emptyopt;
5631       const uschar *rerror;
5632       uschar *subject;
5633       uschar *sub[3];
5634       int save_expand_nmax =
5635         save_expand_strings(save_expand_nstring, save_expand_nlength);
5636
5637       switch(read_subs(sub, 3, 3, &s, skipping, TRUE, US"sg", &resetok))
5638         {
5639         case 1: goto EXPAND_FAILED_CURLY;
5640         case 2:
5641         case 3: goto EXPAND_FAILED;
5642         }
5643
5644       /* Compile the regular expression */
5645
5646       re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror, &roffset,
5647         NULL);
5648
5649       if (re == NULL)
5650         {
5651         expand_string_message = string_sprintf("regular expression error in "
5652           "\"%s\": %s at offset %d", sub[1], rerror, roffset);
5653         goto EXPAND_FAILED;
5654         }
5655
5656       /* Now run a loop to do the substitutions as often as necessary. It ends
5657       when there are no more matches. Take care over matches of the null string;
5658       do the same thing as Perl does. */
5659
5660       subject = sub[0];
5661       slen = Ustrlen(sub[0]);
5662       moffset = moffsetextra = 0;
5663       emptyopt = 0;
5664
5665       for (;;)
5666         {
5667         int ovector[3*(EXPAND_MAXN+1)];
5668         int n = pcre_exec(re, NULL, CS subject, slen, moffset + moffsetextra,
5669           PCRE_EOPT | emptyopt, ovector, nelem(ovector));
5670         uschar *insert;
5671
5672         /* No match - if we previously set PCRE_NOTEMPTY after a null match, this
5673         is not necessarily the end. We want to repeat the match from one
5674         character further along, but leaving the basic offset the same (for
5675         copying below). We can't be at the end of the string - that was checked
5676         before setting PCRE_NOTEMPTY. If PCRE_NOTEMPTY is not set, we are
5677         finished; copy the remaining string and end the loop. */
5678
5679         if (n < 0)
5680           {
5681           if (emptyopt != 0)
5682             {
5683             moffsetextra = 1;
5684             emptyopt = 0;
5685             continue;
5686             }
5687           yield = string_catn(yield, subject+moffset, slen-moffset);
5688           break;
5689           }
5690
5691         /* Match - set up for expanding the replacement. */
5692
5693         if (n == 0) n = EXPAND_MAXN + 1;
5694         expand_nmax = 0;
5695         for (int nn = 0; nn < n*2; nn += 2)
5696           {
5697           expand_nstring[expand_nmax] = subject + ovector[nn];
5698           expand_nlength[expand_nmax++] = ovector[nn+1] - ovector[nn];
5699           }
5700         expand_nmax--;
5701
5702         /* Copy the characters before the match, plus the expanded insertion. */
5703
5704         yield = string_catn(yield, subject + moffset, ovector[0] - moffset);
5705         insert = expand_string(sub[2]);
5706         if (insert == NULL) goto EXPAND_FAILED;
5707         yield = string_cat(yield, insert);
5708
5709         moffset = ovector[1];
5710         moffsetextra = 0;
5711         emptyopt = 0;
5712
5713         /* If we have matched an empty string, first check to see if we are at
5714         the end of the subject. If so, the loop is over. Otherwise, mimic
5715         what Perl's /g options does. This turns out to be rather cunning. First
5716         we set PCRE_NOTEMPTY and PCRE_ANCHORED and try the match a non-empty
5717         string at the same point. If this fails (picked up above) we advance to
5718         the next character. */
5719
5720         if (ovector[0] == ovector[1])
5721           {
5722           if (ovector[0] == slen) break;
5723           emptyopt = PCRE_NOTEMPTY | PCRE_ANCHORED;
5724           }
5725         }
5726
5727       /* All done - restore numerical variables. */
5728
5729       restore_expand_strings(save_expand_nmax, save_expand_nstring,
5730         save_expand_nlength);
5731       continue;
5732       }
5733
5734     /* Handle keyed and numbered substring extraction. If the first argument
5735     consists entirely of digits, then a numerical extraction is assumed. */
5736
5737     case EITEM_EXTRACT:
5738       {
5739       int field_number = 1;
5740       BOOL field_number_set = FALSE;
5741       uschar *save_lookup_value = lookup_value;
5742       uschar *sub[3];
5743       int save_expand_nmax =
5744         save_expand_strings(save_expand_nstring, save_expand_nlength);
5745
5746       /* On reflection the original behaviour of extract-json for a string
5747       result, leaving it quoted, was a mistake.  But it was already published,
5748       hence the addition of jsons.  In a future major version, make json
5749       work like josons, and withdraw jsons. */
5750
5751       enum {extract_basic, extract_json, extract_jsons} fmt = extract_basic;
5752
5753       while (isspace(*s)) s++;
5754
5755       /* Check for a format-variant specifier */
5756
5757       if (*s != '{')                                    /*}*/
5758         if (Ustrncmp(s, "json", 4) == 0)
5759           if (*(s += 4) == 's')
5760             {fmt = extract_jsons; s++;}
5761           else
5762             fmt = extract_json;
5763
5764       /* While skipping we cannot rely on the data for expansions being
5765       available (eg. $item) hence cannot decide on numeric vs. keyed.
5766       Read a maximum of 5 arguments (including the yes/no) */
5767
5768       if (skipping)
5769         {
5770         for (int j = 5; j > 0 && *s == '{'; j--)                /*'}'*/
5771           {
5772           if (!expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok))
5773             goto EXPAND_FAILED;                                 /*'{'*/
5774           if (*s++ != '}')
5775             {
5776             expand_string_message = US"missing '{' for arg of extract";
5777             goto EXPAND_FAILED_CURLY;
5778             }
5779           while (isspace(*s)) s++;
5780           }
5781         if (  Ustrncmp(s, "fail", 4) == 0                       /*'{'*/
5782            && (s[4] == '}' || s[4] == ' ' || s[4] == '\t' || !s[4])
5783            )
5784           {
5785           s += 4;
5786           while (isspace(*s)) s++;
5787           }                                                     /*'{'*/
5788         if (*s != '}')
5789           {
5790           expand_string_message = US"missing '}' closing extract";
5791           goto EXPAND_FAILED_CURLY;
5792           }
5793         }
5794
5795       else for (int i = 0, j = 2; i < j; i++) /* Read the proper number of arguments */
5796         {
5797         while (isspace(*s)) s++;
5798         if (*s == '{')                                          /*'}'*/
5799           {
5800           sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
5801           if (sub[i] == NULL) goto EXPAND_FAILED;               /*'{'*/
5802           if (*s++ != '}')
5803             {
5804             expand_string_message = string_sprintf(
5805               "missing '}' closing arg %d of extract", i+1);
5806             goto EXPAND_FAILED_CURLY;
5807             }
5808
5809           /* After removal of leading and trailing white space, the first
5810           argument must not be empty; if it consists entirely of digits
5811           (optionally preceded by a minus sign), this is a numerical
5812           extraction, and we expect 3 arguments (normal) or 2 (json). */
5813
5814           if (i == 0)
5815             {
5816             int len;
5817             int x = 0;
5818             uschar *p = sub[0];
5819
5820             while (isspace(*p)) p++;
5821             sub[0] = p;
5822
5823             len = Ustrlen(p);
5824             while (len > 0 && isspace(p[len-1])) len--;
5825             p[len] = 0;
5826
5827             if (*p == 0)
5828               {
5829               expand_string_message = US"first argument of \"extract\" must "
5830                 "not be empty";
5831               goto EXPAND_FAILED;
5832               }
5833
5834             if (*p == '-')
5835               {
5836               field_number = -1;
5837               p++;
5838               }
5839             while (*p != 0 && isdigit(*p)) x = x * 10 + *p++ - '0';
5840             if (*p == 0)
5841               {
5842               field_number *= x;
5843               if (fmt == extract_basic) j = 3;               /* Need 3 args */
5844               field_number_set = TRUE;
5845               }
5846             }
5847           }
5848         else
5849           {
5850           expand_string_message = string_sprintf(
5851             "missing '{' for arg %d of extract", i+1);
5852           goto EXPAND_FAILED_CURLY;
5853           }
5854         }
5855
5856       /* Extract either the numbered or the keyed substring into $value. If
5857       skipping, just pretend the extraction failed. */
5858
5859       if (skipping)
5860         lookup_value = NULL;
5861       else switch (fmt)
5862         {
5863         case extract_basic:
5864           lookup_value = field_number_set
5865             ? expand_gettokened(field_number, sub[1], sub[2])
5866             : expand_getkeyed(sub[0], sub[1]);
5867           break;
5868
5869         case extract_json:
5870         case extract_jsons:
5871           {
5872           uschar * s, * item;
5873           const uschar * list;
5874
5875           /* Array: Bracket-enclosed and comma-separated.
5876           Object: Brace-enclosed, comma-sep list of name:value pairs */
5877
5878           if (!(s = dewrap(sub[1], field_number_set ? US"[]" : US"{}")))
5879             {
5880             expand_string_message =
5881               string_sprintf("%s wrapping %s for extract json",
5882                 expand_string_message,
5883                 field_number_set ? "array" : "object");
5884             goto EXPAND_FAILED_CURLY;
5885             }
5886
5887           list = s;
5888           if (field_number_set)
5889             {
5890             if (field_number <= 0)
5891               {
5892               expand_string_message = US"first argument of \"extract\" must "
5893                 "be greater than zero";
5894               goto EXPAND_FAILED;
5895               }
5896             while (field_number > 0 && (item = json_nextinlist(&list)))
5897               field_number--;
5898             if ((lookup_value = s = item))
5899               {
5900               while (*s) s++;
5901               while (--s >= lookup_value && isspace(*s)) *s = '\0';
5902               }
5903             }
5904           else
5905             {
5906             lookup_value = NULL;
5907             while ((item = json_nextinlist(&list)))
5908               {
5909               /* Item is:  string name-sep value.  string is quoted.
5910               Dequote the string and compare with the search key. */
5911
5912               if (!(item = dewrap(item, US"\"\"")))
5913                 {
5914                 expand_string_message =
5915                   string_sprintf("%s wrapping string key for extract json",
5916                     expand_string_message);
5917                 goto EXPAND_FAILED_CURLY;
5918                 }
5919               if (Ustrcmp(item, sub[0]) == 0)   /*XXX should be a UTF8-compare */
5920                 {
5921                 s = item + Ustrlen(item) + 1;
5922                 while (isspace(*s)) s++;
5923                 if (*s != ':')
5924                   {
5925                   expand_string_message = string_sprintf(
5926                     "missing object value-separator for extract json");
5927                   goto EXPAND_FAILED_CURLY;
5928                   }
5929                 s++;
5930                 while (isspace(*s)) s++;
5931                 lookup_value = s;
5932                 break;
5933                 }
5934               }
5935             }
5936           }
5937
5938           if (  fmt == extract_jsons
5939              && lookup_value
5940              && !(lookup_value = dewrap(lookup_value, US"\"\"")))
5941             {
5942             expand_string_message =
5943               string_sprintf("%s wrapping string result for extract jsons",
5944                 expand_string_message);
5945             goto EXPAND_FAILED_CURLY;
5946             }
5947           break;        /* json/s */
5948         }
5949
5950       /* If no string follows, $value gets substituted; otherwise there can
5951       be yes/no strings, as for lookup or if. */
5952
5953       switch(process_yesno(
5954                skipping,                     /* were previously skipping */
5955                lookup_value != NULL,         /* success/failure indicator */
5956                save_lookup_value,            /* value to reset for string2 */
5957                &s,                           /* input pointer */
5958                &yield,                       /* output pointer */
5959                US"extract",                  /* condition type */
5960                &resetok))
5961         {
5962         case 1: goto EXPAND_FAILED;          /* when all is well, the */
5963         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
5964         }
5965
5966       /* All done - restore numerical variables. */
5967
5968       restore_expand_strings(save_expand_nmax, save_expand_nstring,
5969         save_expand_nlength);
5970
5971       continue;
5972       }
5973
5974     /* return the Nth item from a list */
5975
5976     case EITEM_LISTEXTRACT:
5977       {
5978       int field_number = 1;
5979       uschar *save_lookup_value = lookup_value;
5980       uschar *sub[2];
5981       int save_expand_nmax =
5982         save_expand_strings(save_expand_nstring, save_expand_nlength);
5983
5984       /* Read the field & list arguments */
5985
5986       for (int i = 0; i < 2; i++)
5987         {
5988         while (isspace(*s)) s++;
5989         if (*s != '{')                                  /*'}'*/
5990           {
5991           expand_string_message = string_sprintf(
5992             "missing '{' for arg %d of listextract", i+1);
5993           goto EXPAND_FAILED_CURLY;
5994           }
5995
5996         sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
5997         if (!sub[i])     goto EXPAND_FAILED;            /*{*/
5998         if (*s++ != '}')
5999           {
6000           expand_string_message = string_sprintf(
6001             "missing '}' closing arg %d of listextract", i+1);
6002           goto EXPAND_FAILED_CURLY;
6003           }
6004
6005         /* After removal of leading and trailing white space, the first
6006         argument must be numeric and nonempty. */
6007
6008         if (i == 0)
6009           {
6010           int len;
6011           int x = 0;
6012           uschar *p = sub[0];
6013
6014           while (isspace(*p)) p++;
6015           sub[0] = p;
6016
6017           len = Ustrlen(p);
6018           while (len > 0 && isspace(p[len-1])) len--;
6019           p[len] = 0;
6020
6021           if (!*p && !skipping)
6022             {
6023             expand_string_message = US"first argument of \"listextract\" must "
6024               "not be empty";
6025             goto EXPAND_FAILED;
6026             }
6027
6028           if (*p == '-')
6029             {
6030             field_number = -1;
6031             p++;
6032             }
6033           while (*p && isdigit(*p)) x = x * 10 + *p++ - '0';
6034           if (*p)
6035             {
6036             expand_string_message = US"first argument of \"listextract\" must "
6037               "be numeric";
6038             goto EXPAND_FAILED;
6039             }
6040           field_number *= x;
6041           }
6042         }
6043
6044       /* Extract the numbered element into $value. If
6045       skipping, just pretend the extraction failed. */
6046
6047       lookup_value = skipping ? NULL : expand_getlistele(field_number, sub[1]);
6048
6049       /* If no string follows, $value gets substituted; otherwise there can
6050       be yes/no strings, as for lookup or if. */
6051
6052       switch(process_yesno(
6053                skipping,                     /* were previously skipping */
6054                lookup_value != NULL,         /* success/failure indicator */
6055                save_lookup_value,            /* value to reset for string2 */
6056                &s,                           /* input pointer */
6057                &yield,                       /* output pointer */
6058                US"listextract",              /* condition type */
6059                &resetok))
6060         {
6061         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6062         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6063         }
6064
6065       /* All done - restore numerical variables. */
6066
6067       restore_expand_strings(save_expand_nmax, save_expand_nstring,
6068         save_expand_nlength);
6069
6070       continue;
6071       }
6072
6073 #ifndef DISABLE_TLS
6074     case EITEM_CERTEXTRACT:
6075       {
6076       uschar *save_lookup_value = lookup_value;
6077       uschar *sub[2];
6078       int save_expand_nmax =
6079         save_expand_strings(save_expand_nstring, save_expand_nlength);
6080
6081       /* Read the field argument */
6082       while (isspace(*s)) s++;
6083       if (*s != '{')                                    /*}*/
6084         {
6085         expand_string_message = US"missing '{' for field arg of certextract";
6086         goto EXPAND_FAILED_CURLY;
6087         }
6088       sub[0] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
6089       if (!sub[0])     goto EXPAND_FAILED;              /*{*/
6090       if (*s++ != '}')
6091         {
6092         expand_string_message = US"missing '}' closing field arg of certextract";
6093         goto EXPAND_FAILED_CURLY;
6094         }
6095       /* strip spaces fore & aft */
6096       {
6097       int len;
6098       uschar *p = sub[0];
6099
6100       while (isspace(*p)) p++;
6101       sub[0] = p;
6102
6103       len = Ustrlen(p);
6104       while (len > 0 && isspace(p[len-1])) len--;
6105       p[len] = 0;
6106       }
6107
6108       /* inspect the cert argument */
6109       while (isspace(*s)) s++;
6110       if (*s != '{')                                    /*}*/
6111         {
6112         expand_string_message = US"missing '{' for cert variable arg of certextract";
6113         goto EXPAND_FAILED_CURLY;
6114         }
6115       if (*++s != '$')
6116         {
6117         expand_string_message = US"second argument of \"certextract\" must "
6118           "be a certificate variable";
6119         goto EXPAND_FAILED;
6120         }
6121       sub[1] = expand_string_internal(s+1, TRUE, &s, skipping, FALSE, &resetok);
6122       if (!sub[1])     goto EXPAND_FAILED;              /*{*/
6123       if (*s++ != '}')
6124         {
6125         expand_string_message = US"missing '}' closing cert variable arg of certextract";
6126         goto EXPAND_FAILED_CURLY;
6127         }
6128
6129       if (skipping)
6130         lookup_value = NULL;
6131       else
6132         {
6133         lookup_value = expand_getcertele(sub[0], sub[1]);
6134         if (*expand_string_message) goto EXPAND_FAILED;
6135         }
6136       switch(process_yesno(
6137                skipping,                     /* were previously skipping */
6138                lookup_value != NULL,         /* success/failure indicator */
6139                save_lookup_value,            /* value to reset for string2 */
6140                &s,                           /* input pointer */
6141                &yield,                       /* output pointer */
6142                US"certextract",              /* condition type */
6143                &resetok))
6144         {
6145         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6146         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6147         }
6148
6149       restore_expand_strings(save_expand_nmax, save_expand_nstring,
6150         save_expand_nlength);
6151       continue;
6152       }
6153 #endif  /*DISABLE_TLS*/
6154
6155     /* Handle list operations */
6156
6157     case EITEM_FILTER:
6158     case EITEM_MAP:
6159     case EITEM_REDUCE:
6160       {
6161       int sep = 0;
6162       int save_ptr = yield->ptr;
6163       uschar outsep[2] = { '\0', '\0' };
6164       const uschar *list, *expr, *temp;
6165       uschar *save_iterate_item = iterate_item;
6166       uschar *save_lookup_value = lookup_value;
6167
6168       while (isspace(*s)) s++;
6169       if (*s++ != '{')
6170         {
6171         expand_string_message =
6172           string_sprintf("missing '{' for first arg of %s", name);
6173         goto EXPAND_FAILED_CURLY;
6174         }
6175
6176       list = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
6177       if (list == NULL) goto EXPAND_FAILED;
6178       if (*s++ != '}')
6179         {
6180         expand_string_message =
6181           string_sprintf("missing '}' closing first arg of %s", name);
6182         goto EXPAND_FAILED_CURLY;
6183         }
6184
6185       if (item_type == EITEM_REDUCE)
6186         {
6187         uschar * t;
6188         while (isspace(*s)) s++;
6189         if (*s++ != '{')
6190           {
6191           expand_string_message = US"missing '{' for second arg of reduce";
6192           goto EXPAND_FAILED_CURLY;
6193           }
6194         t = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
6195         if (!t) goto EXPAND_FAILED;
6196         lookup_value = t;
6197         if (*s++ != '}')
6198           {
6199           expand_string_message = US"missing '}' closing second arg of reduce";
6200           goto EXPAND_FAILED_CURLY;
6201           }
6202         }
6203
6204       while (isspace(*s)) s++;
6205       if (*s++ != '{')
6206         {
6207         expand_string_message =
6208           string_sprintf("missing '{' for last arg of %s", name);
6209         goto EXPAND_FAILED_CURLY;
6210         }
6211
6212       expr = s;
6213
6214       /* For EITEM_FILTER, call eval_condition once, with result discarded (as
6215       if scanning a "false" part). This allows us to find the end of the
6216       condition, because if the list is empty, we won't actually evaluate the
6217       condition for real. For EITEM_MAP and EITEM_REDUCE, do the same, using
6218       the normal internal expansion function. */
6219
6220       if (item_type == EITEM_FILTER)
6221         {
6222         temp = eval_condition(expr, &resetok, NULL);
6223         if (temp != NULL) s = temp;
6224         }
6225       else
6226         temp = expand_string_internal(s, TRUE, &s, TRUE, TRUE, &resetok);
6227
6228       if (temp == NULL)
6229         {
6230         expand_string_message = string_sprintf("%s inside \"%s\" item",
6231           expand_string_message, name);
6232         goto EXPAND_FAILED;
6233         }
6234
6235       while (isspace(*s)) s++;
6236       if (*s++ != '}')
6237         {                                               /*{*/
6238         expand_string_message = string_sprintf("missing } at end of condition "
6239           "or expression inside \"%s\"; could be an unquoted } in the content",
6240           name);
6241         goto EXPAND_FAILED;
6242         }
6243
6244       while (isspace(*s)) s++;                          /*{*/
6245       if (*s++ != '}')
6246         {                                               /*{*/
6247         expand_string_message = string_sprintf("missing } at end of \"%s\"",
6248           name);
6249         goto EXPAND_FAILED;
6250         }
6251
6252       /* If we are skipping, we can now just move on to the next item. When
6253       processing for real, we perform the iteration. */
6254
6255       if (skipping) continue;
6256       while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
6257         {
6258         *outsep = (uschar)sep;      /* Separator as a string */
6259
6260         DEBUG(D_expand) debug_printf_indent("%s: $item = '%s'  $value = '%s'\n",
6261                           name, iterate_item, lookup_value);
6262
6263         if (item_type == EITEM_FILTER)
6264           {
6265           BOOL condresult;
6266           if (eval_condition(expr, &resetok, &condresult) == NULL)
6267             {
6268             iterate_item = save_iterate_item;
6269             lookup_value = save_lookup_value;
6270             expand_string_message = string_sprintf("%s inside \"%s\" condition",
6271               expand_string_message, name);
6272             goto EXPAND_FAILED;
6273             }
6274           DEBUG(D_expand) debug_printf_indent("%s: condition is %s\n", name,
6275             condresult? "true":"false");
6276           if (condresult)
6277             temp = iterate_item;    /* TRUE => include this item */
6278           else
6279             continue;               /* FALSE => skip this item */
6280           }
6281
6282         /* EITEM_MAP and EITEM_REDUCE */
6283
6284         else
6285           {
6286           uschar * t = expand_string_internal(expr, TRUE, NULL, skipping, TRUE, &resetok);
6287           temp = t;
6288           if (temp == NULL)
6289             {
6290             iterate_item = save_iterate_item;
6291             expand_string_message = string_sprintf("%s inside \"%s\" item",
6292               expand_string_message, name);
6293             goto EXPAND_FAILED;
6294             }
6295           if (item_type == EITEM_REDUCE)
6296             {
6297             lookup_value = t;         /* Update the value of $value */
6298             continue;                 /* and continue the iteration */
6299             }
6300           }
6301
6302         /* We reach here for FILTER if the condition is true, always for MAP,
6303         and never for REDUCE. The value in "temp" is to be added to the output
6304         list that is being created, ensuring that any occurrences of the
6305         separator character are doubled. Unless we are dealing with the first
6306         item of the output list, add in a space if the new item begins with the
6307         separator character, or is an empty string. */
6308
6309         if (yield->ptr != save_ptr && (temp[0] == *outsep || temp[0] == 0))
6310           yield = string_catn(yield, US" ", 1);
6311
6312         /* Add the string in "temp" to the output list that we are building,
6313         This is done in chunks by searching for the separator character. */
6314
6315         for (;;)
6316           {
6317           size_t seglen = Ustrcspn(temp, outsep);
6318
6319           yield = string_catn(yield, temp, seglen + 1);
6320
6321           /* If we got to the end of the string we output one character
6322           too many; backup and end the loop. Otherwise arrange to double the
6323           separator. */
6324
6325           if (temp[seglen] == '\0') { yield->ptr--; break; }
6326           yield = string_catn(yield, outsep, 1);
6327           temp += seglen + 1;
6328           }
6329
6330         /* Output a separator after the string: we will remove the redundant
6331         final one at the end. */
6332
6333         yield = string_catn(yield, outsep, 1);
6334         }   /* End of iteration over the list loop */
6335
6336       /* REDUCE has generated no output above: output the final value of
6337       $value. */
6338
6339       if (item_type == EITEM_REDUCE)
6340         {
6341         yield = string_cat(yield, lookup_value);
6342         lookup_value = save_lookup_value;  /* Restore $value */
6343         }
6344
6345       /* FILTER and MAP generate lists: if they have generated anything, remove
6346       the redundant final separator. Even though an empty item at the end of a
6347       list does not count, this is tidier. */
6348
6349       else if (yield->ptr != save_ptr) yield->ptr--;
6350
6351       /* Restore preserved $item */
6352
6353       iterate_item = save_iterate_item;
6354       continue;
6355       }
6356
6357     case EITEM_SORT:
6358       {
6359       int cond_type;
6360       int sep = 0;
6361       const uschar *srclist, *cmp, *xtract;
6362       uschar * opname, * srcitem;
6363       const uschar *dstlist = NULL, *dstkeylist = NULL;
6364       uschar * tmp;
6365       uschar *save_iterate_item = iterate_item;
6366
6367       while (isspace(*s)) s++;
6368       if (*s++ != '{')
6369         {
6370         expand_string_message = US"missing '{' for list arg of sort";
6371         goto EXPAND_FAILED_CURLY;
6372         }
6373
6374       srclist = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
6375       if (!srclist) goto EXPAND_FAILED;
6376       if (*s++ != '}')
6377         {
6378         expand_string_message = US"missing '}' closing list arg of sort";
6379         goto EXPAND_FAILED_CURLY;
6380         }
6381
6382       while (isspace(*s)) s++;
6383       if (*s++ != '{')
6384         {
6385         expand_string_message = US"missing '{' for comparator arg of sort";
6386         goto EXPAND_FAILED_CURLY;
6387         }
6388
6389       cmp = expand_string_internal(s, TRUE, &s, skipping, FALSE, &resetok);
6390       if (!cmp) goto EXPAND_FAILED;
6391       if (*s++ != '}')
6392         {
6393         expand_string_message = US"missing '}' closing comparator arg of sort";
6394         goto EXPAND_FAILED_CURLY;
6395         }
6396
6397       if ((cond_type = identify_operator(&cmp, &opname)) == -1)
6398         {
6399         if (!expand_string_message)
6400           expand_string_message = string_sprintf("unknown condition \"%s\"", s);
6401         goto EXPAND_FAILED;
6402         }
6403       switch(cond_type)
6404         {
6405         case ECOND_NUM_L: case ECOND_NUM_LE:
6406         case ECOND_NUM_G: case ECOND_NUM_GE:
6407         case ECOND_STR_GE: case ECOND_STR_GEI: case ECOND_STR_GT: case ECOND_STR_GTI:
6408         case ECOND_STR_LE: case ECOND_STR_LEI: case ECOND_STR_LT: case ECOND_STR_LTI:
6409           break;
6410
6411         default:
6412           expand_string_message = US"comparator not handled for sort";
6413           goto EXPAND_FAILED;
6414         }
6415
6416       while (isspace(*s)) s++;
6417       if (*s++ != '{')
6418         {
6419         expand_string_message = US"missing '{' for extractor arg of sort";
6420         goto EXPAND_FAILED_CURLY;
6421         }
6422
6423       xtract = s;
6424       tmp = expand_string_internal(s, TRUE, &s, TRUE, TRUE, &resetok);
6425       if (!tmp) goto EXPAND_FAILED;
6426       xtract = string_copyn(xtract, s - xtract);
6427
6428       if (*s++ != '}')
6429         {
6430         expand_string_message = US"missing '}' closing extractor arg of sort";
6431         goto EXPAND_FAILED_CURLY;
6432         }
6433                                                         /*{*/
6434       if (*s++ != '}')
6435         {                                               /*{*/
6436         expand_string_message = US"missing } at end of \"sort\"";
6437         goto EXPAND_FAILED;
6438         }
6439
6440       if (skipping) continue;
6441
6442       while ((srcitem = string_nextinlist(&srclist, &sep, NULL, 0)))
6443         {
6444         uschar * srcfield, * dstitem;
6445         gstring * newlist = NULL;
6446         gstring * newkeylist = NULL;
6447
6448         DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", name, srcitem);
6449
6450         /* extract field for comparisons */
6451         iterate_item = srcitem;
6452         if (  !(srcfield = expand_string_internal(xtract, FALSE, NULL, FALSE,
6453                                           TRUE, &resetok))
6454            || !*srcfield)
6455           {
6456           expand_string_message = string_sprintf(
6457               "field-extract in sort: \"%s\"", xtract);
6458           goto EXPAND_FAILED;
6459           }
6460
6461         /* Insertion sort */
6462
6463         /* copy output list until new-item < list-item */
6464         while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
6465           {
6466           uschar * dstfield;
6467
6468           /* field for comparison */
6469           if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
6470             goto sort_mismatch;
6471
6472           /* String-comparator names start with a letter; numeric names do not */
6473
6474           if (sortsbefore(cond_type, isalpha(opname[0]),
6475               srcfield, dstfield))
6476             {
6477             /* New-item sorts before this dst-item.  Append new-item,
6478             then dst-item, then remainder of dst list. */
6479
6480             newlist = string_append_listele(newlist, sep, srcitem);
6481             newkeylist = string_append_listele(newkeylist, sep, srcfield);
6482             srcitem = NULL;
6483
6484             newlist = string_append_listele(newlist, sep, dstitem);
6485             newkeylist = string_append_listele(newkeylist, sep, dstfield);
6486
6487             while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
6488               {
6489               if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
6490                 goto sort_mismatch;
6491               newlist = string_append_listele(newlist, sep, dstitem);
6492               newkeylist = string_append_listele(newkeylist, sep, dstfield);
6493               }
6494
6495             break;
6496             }
6497
6498           newlist = string_append_listele(newlist, sep, dstitem);
6499           newkeylist = string_append_listele(newkeylist, sep, dstfield);
6500           }
6501
6502         /* If we ran out of dstlist without consuming srcitem, append it */
6503         if (srcitem)
6504           {
6505           newlist = string_append_listele(newlist, sep, srcitem);
6506           newkeylist = string_append_listele(newkeylist, sep, srcfield);
6507           }
6508
6509         dstlist = newlist->s;
6510         dstkeylist = newkeylist->s;
6511
6512         DEBUG(D_expand) debug_printf_indent("%s: dstlist = \"%s\"\n", name, dstlist);
6513         DEBUG(D_expand) debug_printf_indent("%s: dstkeylist = \"%s\"\n", name, dstkeylist);
6514         }
6515
6516       if (dstlist)
6517         yield = string_cat(yield, dstlist);
6518
6519       /* Restore preserved $item */
6520       iterate_item = save_iterate_item;
6521       continue;
6522
6523       sort_mismatch:
6524         expand_string_message = US"Internal error in sort (list mismatch)";
6525         goto EXPAND_FAILED;
6526       }
6527
6528
6529     /* If ${dlfunc } support is configured, handle calling dynamically-loaded
6530     functions, unless locked out at this time. Syntax is ${dlfunc{file}{func}}
6531     or ${dlfunc{file}{func}{arg}} or ${dlfunc{file}{func}{arg1}{arg2}} or up to
6532     a maximum of EXPAND_DLFUNC_MAX_ARGS arguments (defined below). */
6533
6534     #define EXPAND_DLFUNC_MAX_ARGS 8
6535
6536     case EITEM_DLFUNC:
6537 #ifndef EXPAND_DLFUNC
6538       expand_string_message = US"\"${dlfunc\" encountered, but this facility "  /*}*/
6539         "is not included in this binary";
6540       goto EXPAND_FAILED;
6541
6542 #else   /* EXPAND_DLFUNC */
6543       {
6544       tree_node *t;
6545       exim_dlfunc_t *func;
6546       uschar *result;
6547       int status, argc;
6548       uschar *argv[EXPAND_DLFUNC_MAX_ARGS + 3];
6549
6550       if ((expand_forbid & RDO_DLFUNC) != 0)
6551         {
6552         expand_string_message =
6553           US"dynamically-loaded functions are not permitted";
6554         goto EXPAND_FAILED;
6555         }
6556
6557       switch(read_subs(argv, EXPAND_DLFUNC_MAX_ARGS + 2, 2, &s, skipping,
6558            TRUE, US"dlfunc", &resetok))
6559         {
6560         case 1: goto EXPAND_FAILED_CURLY;
6561         case 2:
6562         case 3: goto EXPAND_FAILED;
6563         }
6564
6565       /* If skipping, we don't actually do anything */
6566
6567       if (skipping) continue;
6568
6569       /* Look up the dynamically loaded object handle in the tree. If it isn't
6570       found, dlopen() the file and put the handle in the tree for next time. */
6571
6572       if (!(t = tree_search(dlobj_anchor, argv[0])))
6573         {
6574         void *handle = dlopen(CS argv[0], RTLD_LAZY);
6575         if (handle == NULL)
6576           {
6577           expand_string_message = string_sprintf("dlopen \"%s\" failed: %s",
6578             argv[0], dlerror());
6579           log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
6580           goto EXPAND_FAILED;
6581           }
6582         t = store_get_perm(sizeof(tree_node) + Ustrlen(argv[0]));
6583         Ustrcpy(t->name, argv[0]);
6584         t->data.ptr = handle;
6585         (void)tree_insertnode(&dlobj_anchor, t);
6586         }
6587
6588       /* Having obtained the dynamically loaded object handle, look up the
6589       function pointer. */
6590
6591       func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1]);
6592       if (func == NULL)
6593         {
6594         expand_string_message = string_sprintf("dlsym \"%s\" in \"%s\" failed: "
6595           "%s", argv[1], argv[0], dlerror());
6596         log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message);
6597         goto EXPAND_FAILED;
6598         }
6599
6600       /* Call the function and work out what to do with the result. If it
6601       returns OK, we have a replacement string; if it returns DEFER then
6602       expansion has failed in a non-forced manner; if it returns FAIL then
6603       failure was forced; if it returns ERROR or any other value there's a
6604       problem, so panic slightly. In any case, assume that the function has
6605       side-effects on the store that must be preserved. */
6606
6607       resetok = FALSE;
6608       result = NULL;
6609       for (argc = 0; argv[argc] != NULL; argc++);
6610       status = func(&result, argc - 2, &argv[2]);
6611       if(status == OK)
6612         {
6613         if (result == NULL) result = US"";
6614         yield = string_cat(yield, result);
6615         continue;
6616         }
6617       else
6618         {
6619         expand_string_message = result == NULL ? US"(no message)" : result;
6620         if(status == FAIL_FORCED) f.expand_string_forcedfail = TRUE;
6621           else if(status != FAIL)
6622             log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
6623               argv[0], argv[1], status, expand_string_message);
6624         goto EXPAND_FAILED;
6625         }
6626       }
6627 #endif /* EXPAND_DLFUNC */
6628
6629     case EITEM_ENV:     /* ${env {name} {val_if_found} {val_if_unfound}} */
6630       {
6631       uschar * key;
6632       uschar *save_lookup_value = lookup_value;
6633
6634       while (isspace(*s)) s++;
6635       if (*s != '{')                                    /*}*/
6636         goto EXPAND_FAILED;
6637
6638       key = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
6639       if (!key) goto EXPAND_FAILED;                     /*{*/
6640       if (*s++ != '}')
6641         {
6642         expand_string_message = US"missing '{' for name arg of env";
6643         goto EXPAND_FAILED_CURLY;
6644         }
6645
6646       lookup_value = US getenv(CS key);
6647
6648       switch(process_yesno(
6649                skipping,                     /* were previously skipping */
6650                lookup_value != NULL,         /* success/failure indicator */
6651                save_lookup_value,            /* value to reset for string2 */
6652                &s,                           /* input pointer */
6653                &yield,                       /* output pointer */
6654                US"env",                      /* condition type */
6655                &resetok))
6656         {
6657         case 1: goto EXPAND_FAILED;          /* when all is well, the */
6658         case 2: goto EXPAND_FAILED_CURLY;    /* returned value is 0 */
6659         }
6660       continue;
6661       }
6662     }   /* EITEM_* switch */
6663
6664   /* Control reaches here if the name is not recognized as one of the more
6665   complicated expansion items. Check for the "operator" syntax (name terminated
6666   by a colon). Some of the operators have arguments, separated by _ from the
6667   name. */
6668
6669   if (*s == ':')
6670     {
6671     int c;
6672     uschar *arg = NULL;
6673     uschar *sub;
6674 #ifndef DISABLE_TLS
6675     var_entry *vp = NULL;
6676 #endif
6677
6678     /* Owing to an historical mis-design, an underscore may be part of the
6679     operator name, or it may introduce arguments.  We therefore first scan the
6680     table of names that contain underscores. If there is no match, we cut off
6681     the arguments and then scan the main table. */
6682
6683     if ((c = chop_match(name, op_table_underscore,
6684                         nelem(op_table_underscore))) < 0)
6685       {
6686       arg = Ustrchr(name, '_');
6687       if (arg != NULL) *arg = 0;
6688       c = chop_match(name, op_table_main, nelem(op_table_main));
6689       if (c >= 0) c += nelem(op_table_underscore);
6690       if (arg != NULL) *arg++ = '_';   /* Put back for error messages */
6691       }
6692
6693     /* Deal specially with operators that might take a certificate variable
6694     as we do not want to do the usual expansion. For most, expand the string.*/
6695     switch(c)
6696       {
6697 #ifndef DISABLE_TLS
6698       case EOP_MD5:
6699       case EOP_SHA1:
6700       case EOP_SHA256:
6701       case EOP_BASE64:
6702         if (s[1] == '$')
6703           {
6704           const uschar * s1 = s;
6705           sub = expand_string_internal(s+2, TRUE, &s1, skipping,
6706                   FALSE, &resetok);
6707           if (!sub)       goto EXPAND_FAILED;           /*{*/
6708           if (*s1 != '}')
6709             {
6710             expand_string_message =
6711               string_sprintf("missing '}' closing cert arg of %s", name);
6712             goto EXPAND_FAILED_CURLY;
6713             }
6714           if ((vp = find_var_ent(sub)) && vp->type == vtype_cert)
6715             {
6716             s = s1+1;
6717             break;
6718             }
6719           vp = NULL;
6720           }
6721         /*FALLTHROUGH*/
6722 #endif
6723       default:
6724         sub = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok);
6725         if (!sub) goto EXPAND_FAILED;
6726         s++;
6727         break;
6728       }
6729
6730     /* If we are skipping, we don't need to perform the operation at all.
6731     This matters for operations like "mask", because the data may not be
6732     in the correct format when skipping. For example, the expression may test
6733     for the existence of $sender_host_address before trying to mask it. For
6734     other operations, doing them may not fail, but it is a waste of time. */
6735
6736     if (skipping && c >= 0) continue;
6737
6738     /* Otherwise, switch on the operator type */
6739
6740     switch(c)
6741       {
6742       case EOP_BASE32:
6743         {
6744         uschar *t;
6745         unsigned long int n = Ustrtoul(sub, &t, 10);
6746         gstring * g = NULL;
6747
6748         if (*t != 0)
6749           {
6750           expand_string_message = string_sprintf("argument for base32 "
6751             "operator is \"%s\", which is not a decimal number", sub);
6752           goto EXPAND_FAILED;
6753           }
6754         for ( ; n; n >>= 5)
6755           g = string_catn(g, &base32_chars[n & 0x1f], 1);
6756
6757         if (g) while (g->ptr > 0) yield = string_catn(yield, &g->s[--g->ptr], 1);
6758         continue;
6759         }
6760
6761       case EOP_BASE32D:
6762         {
6763         uschar *tt = sub;
6764         unsigned long int n = 0;
6765         uschar * s;
6766         while (*tt)
6767           {
6768           uschar * t = Ustrchr(base32_chars, *tt++);
6769           if (t == NULL)
6770             {
6771             expand_string_message = string_sprintf("argument for base32d "
6772               "operator is \"%s\", which is not a base 32 number", sub);
6773             goto EXPAND_FAILED;
6774             }
6775           n = n * 32 + (t - base32_chars);
6776           }
6777         s = string_sprintf("%ld", n);
6778         yield = string_cat(yield, s);
6779         continue;
6780         }
6781
6782       case EOP_BASE62:
6783         {
6784         uschar *t;
6785         unsigned long int n = Ustrtoul(sub, &t, 10);
6786         if (*t != 0)
6787           {
6788           expand_string_message = string_sprintf("argument for base62 "
6789             "operator is \"%s\", which is not a decimal number", sub);
6790           goto EXPAND_FAILED;
6791           }
6792         t = string_base62(n);
6793         yield = string_cat(yield, t);
6794         continue;
6795         }
6796
6797       /* Note that for Darwin and Cygwin, BASE_62 actually has the value 36 */
6798
6799       case EOP_BASE62D:
6800         {
6801         uschar *tt = sub;
6802         unsigned long int n = 0;
6803         while (*tt != 0)
6804           {
6805           uschar *t = Ustrchr(base62_chars, *tt++);
6806           if (t == NULL)
6807             {
6808             expand_string_message = string_sprintf("argument for base62d "
6809               "operator is \"%s\", which is not a base %d number", sub,
6810               BASE_62);
6811             goto EXPAND_FAILED;
6812             }
6813           n = n * BASE_62 + (t - base62_chars);
6814           }
6815         yield = string_fmt_append(yield, "%ld", n);
6816         continue;
6817         }
6818
6819       case EOP_EXPAND:
6820         {
6821         uschar *expanded = expand_string_internal(sub, FALSE, NULL, skipping, TRUE, &resetok);
6822         if (expanded == NULL)
6823           {
6824           expand_string_message =
6825             string_sprintf("internal expansion of \"%s\" failed: %s", sub,
6826               expand_string_message);
6827           goto EXPAND_FAILED;
6828           }
6829         yield = string_cat(yield, expanded);
6830         continue;
6831         }
6832
6833       case EOP_LC:
6834         {
6835         int count = 0;
6836         uschar *t = sub - 1;
6837         while (*(++t) != 0) { *t = tolower(*t); count++; }
6838         yield = string_catn(yield, sub, count);
6839         continue;
6840         }
6841
6842       case EOP_UC:
6843         {
6844         int count = 0;
6845         uschar *t = sub - 1;
6846         while (*(++t) != 0) { *t = toupper(*t); count++; }
6847         yield = string_catn(yield, sub, count);
6848         continue;
6849         }
6850
6851       case EOP_MD5:
6852 #ifndef DISABLE_TLS
6853         if (vp && *(void **)vp->value)
6854           {
6855           uschar * cp = tls_cert_fprt_md5(*(void **)vp->value);
6856           yield = string_cat(yield, cp);
6857           }
6858         else
6859 #endif
6860           {
6861           md5 base;
6862           uschar digest[16];
6863           md5_start(&base);
6864           md5_end(&base, sub, Ustrlen(sub), digest);
6865           for (int j = 0; j < 16; j++)
6866             yield = string_fmt_append(yield, "%02x", digest[j]);
6867           }
6868         continue;
6869
6870       case EOP_SHA1:
6871 #ifndef DISABLE_TLS
6872         if (vp && *(void **)vp->value)
6873           {
6874           uschar * cp = tls_cert_fprt_sha1(*(void **)vp->value);
6875           yield = string_cat(yield, cp);
6876           }
6877         else
6878 #endif
6879           {
6880           hctx h;
6881           uschar digest[20];
6882           sha1_start(&h);
6883           sha1_end(&h, sub, Ustrlen(sub), digest);
6884           for (int j = 0; j < 20; j++)
6885             yield = string_fmt_append(yield, "%02X", digest[j]);
6886           }
6887         continue;
6888
6889       case EOP_SHA2:
6890       case EOP_SHA256:
6891 #ifdef EXIM_HAVE_SHA2
6892         if (vp && *(void **)vp->value)
6893           if (c == EOP_SHA256)
6894             yield = string_cat(yield, tls_cert_fprt_sha256(*(void **)vp->value));
6895           else
6896             expand_string_message = US"sha2_N not supported with certificates";
6897         else
6898           {
6899           hctx h;
6900           blob b;
6901           hashmethod m = !arg ? HASH_SHA2_256
6902             : Ustrcmp(arg, "256") == 0 ? HASH_SHA2_256
6903             : Ustrcmp(arg, "384") == 0 ? HASH_SHA2_384
6904             : Ustrcmp(arg, "512") == 0 ? HASH_SHA2_512
6905             : HASH_BADTYPE;
6906
6907           if (m == HASH_BADTYPE || !exim_sha_init(&h, m))
6908             {
6909             expand_string_message = US"unrecognised sha2 variant";
6910             goto EXPAND_FAILED;
6911             }
6912
6913           exim_sha_update(&h, sub, Ustrlen(sub));
6914           exim_sha_finish(&h, &b);
6915           while (b.len-- > 0)
6916             yield = string_fmt_append(yield, "%02X", *b.data++);
6917           }
6918 #else
6919           expand_string_message = US"sha256 only supported with TLS";
6920 #endif
6921         continue;
6922
6923       case EOP_SHA3:
6924 #ifdef EXIM_HAVE_SHA3
6925         {
6926         hctx h;
6927         blob b;
6928         hashmethod m = !arg ? HASH_SHA3_256
6929           : Ustrcmp(arg, "224") == 0 ? HASH_SHA3_224
6930           : Ustrcmp(arg, "256") == 0 ? HASH_SHA3_256
6931           : Ustrcmp(arg, "384") == 0 ? HASH_SHA3_384
6932           : Ustrcmp(arg, "512") == 0 ? HASH_SHA3_512
6933           : HASH_BADTYPE;
6934
6935         if (m == HASH_BADTYPE || !exim_sha_init(&h, m))
6936           {
6937           expand_string_message = US"unrecognised sha3 variant";
6938           goto EXPAND_FAILED;
6939           }
6940
6941         exim_sha_update(&h, sub, Ustrlen(sub));
6942         exim_sha_finish(&h, &b);
6943         while (b.len-- > 0)
6944           yield = string_fmt_append(yield, "%02X", *b.data++);
6945         }
6946         continue;
6947 #else
6948         expand_string_message = US"sha3 only supported with GnuTLS 3.5.0 + or OpenSSL 1.1.1 +";
6949         goto EXPAND_FAILED;
6950 #endif
6951
6952       /* Convert hex encoding to base64 encoding */
6953
6954       case EOP_HEX2B64:
6955         {
6956         int c = 0;
6957         int b = -1;
6958         uschar *in = sub;
6959         uschar *out = sub;
6960         uschar *enc;
6961
6962         for (enc = sub; *enc; enc++)
6963           {
6964           if (!isxdigit(*enc))
6965             {
6966             expand_string_message = string_sprintf("\"%s\" is not a hex "
6967               "string", sub);
6968             goto EXPAND_FAILED;
6969             }
6970           c++;
6971           }
6972
6973         if ((c & 1) != 0)
6974           {
6975           expand_string_message = string_sprintf("\"%s\" contains an odd "
6976             "number of characters", sub);
6977           goto EXPAND_FAILED;
6978           }
6979
6980         while ((c = *in++) != 0)
6981           {
6982           if (isdigit(c)) c -= '0';
6983           else c = toupper(c) - 'A' + 10;
6984           if (b == -1)
6985             b = c << 4;
6986           else
6987             {
6988             *out++ = b | c;
6989             b = -1;
6990             }
6991           }
6992
6993         enc = b64encode(CUS sub, out - sub);
6994         yield = string_cat(yield, enc);
6995         continue;
6996         }
6997
6998       /* Convert octets outside 0x21..0x7E to \xXX form */
6999
7000       case EOP_HEXQUOTE:
7001         {
7002         uschar *t = sub - 1;
7003         while (*(++t) != 0)
7004           {
7005           if (*t < 0x21 || 0x7E < *t)
7006             yield = string_fmt_append(yield, "\\x%02x", *t);
7007           else
7008             yield = string_catn(yield, t, 1);
7009           }
7010         continue;
7011         }
7012
7013       /* count the number of list elements */
7014
7015       case EOP_LISTCOUNT:
7016         {
7017         int cnt = 0;
7018         int sep = 0;
7019         uschar buffer[256];
7020
7021         while (string_nextinlist(CUSS &sub, &sep, buffer, sizeof(buffer)) != NULL) cnt++;
7022         yield = string_fmt_append(yield, "%d", cnt);
7023         continue;
7024         }
7025
7026       /* expand a named list given the name */
7027       /* handles nested named lists; requotes as colon-sep list */
7028
7029       case EOP_LISTNAMED:
7030         {
7031         tree_node *t = NULL;
7032         const uschar * list;
7033         int sep = 0;
7034         uschar * item;
7035         uschar * suffix = US"";
7036         BOOL needsep = FALSE;
7037         uschar buffer[256];
7038
7039         if (*sub == '+') sub++;
7040         if (arg == NULL)        /* no-argument version */
7041           {
7042           if (!(t = tree_search(addresslist_anchor, sub)) &&
7043               !(t = tree_search(domainlist_anchor,  sub)) &&
7044               !(t = tree_search(hostlist_anchor,    sub)))
7045             t = tree_search(localpartlist_anchor, sub);
7046           }
7047         else switch(*arg)       /* specific list-type version */
7048           {
7049           case 'a': t = tree_search(addresslist_anchor,   sub); suffix = US"_a"; break;
7050           case 'd': t = tree_search(domainlist_anchor,    sub); suffix = US"_d"; break;
7051           case 'h': t = tree_search(hostlist_anchor,      sub); suffix = US"_h"; break;
7052           case 'l': t = tree_search(localpartlist_anchor, sub); suffix = US"_l"; break;
7053           default:
7054             expand_string_message = string_sprintf("bad suffix on \"list\" operator");
7055             goto EXPAND_FAILED;
7056           }
7057
7058         if(!t)
7059           {
7060           expand_string_message = string_sprintf("\"%s\" is not a %snamed list",
7061             sub, !arg?""
7062               : *arg=='a'?"address "
7063               : *arg=='d'?"domain "
7064               : *arg=='h'?"host "
7065               : *arg=='l'?"localpart "
7066               : 0);
7067           goto EXPAND_FAILED;
7068           }
7069
7070         list = ((namedlist_block *)(t->data.ptr))->string;
7071
7072         while ((item = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
7073           {
7074           uschar * buf = US" : ";
7075           if (needsep)
7076             yield = string_catn(yield, buf, 3);
7077           else
7078             needsep = TRUE;
7079
7080           if (*item == '+')     /* list item is itself a named list */
7081             {
7082             uschar * sub = string_sprintf("${listnamed%s:%s}", suffix, item);
7083             item = expand_string_internal(sub, FALSE, NULL, FALSE, TRUE, &resetok);
7084             }
7085           else if (sep != ':')  /* item from non-colon-sep list, re-quote for colon list-separator */
7086             {
7087             char * cp;
7088             char tok[3];
7089             tok[0] = sep; tok[1] = ':'; tok[2] = 0;
7090             while ((cp= strpbrk(CCS item, tok)))
7091               {
7092               yield = string_catn(yield, item, cp - CS item);
7093               if (*cp++ == ':') /* colon in a non-colon-sep list item, needs doubling */
7094                 {
7095                 yield = string_catn(yield, US"::", 2);
7096                 item = US cp;
7097                 }
7098               else              /* sep in item; should already be doubled; emit once */
7099                 {
7100                 yield = string_catn(yield, US tok, 1);
7101                 if (*cp == sep) cp++;
7102                 item = US cp;
7103                 }
7104               }
7105             }
7106           yield = string_cat(yield, item);
7107           }
7108         continue;
7109         }
7110
7111       /* mask applies a mask to an IP address; for example the result of
7112       ${mask:131.111.10.206/28} is 131.111.10.192/28. */
7113
7114       case EOP_MASK:
7115         {
7116         int count;
7117         uschar *endptr;
7118         int binary[4];
7119         int mask, maskoffset;
7120         int type = string_is_ip_address(sub, &maskoffset);
7121         uschar buffer[64];
7122
7123         if (type == 0)
7124           {
7125           expand_string_message = string_sprintf("\"%s\" is not an IP address",
7126            sub);
7127           goto EXPAND_FAILED;
7128           }
7129
7130         if (maskoffset == 0)
7131           {
7132           expand_string_message = string_sprintf("missing mask value in \"%s\"",
7133             sub);
7134           goto EXPAND_FAILED;
7135           }
7136
7137         mask = Ustrtol(sub + maskoffset + 1, &endptr, 10);
7138
7139         if (*endptr != 0 || mask < 0 || mask > ((type == 4)? 32 : 128))
7140           {
7141           expand_string_message = string_sprintf("mask value too big in \"%s\"",
7142             sub);
7143           goto EXPAND_FAILED;
7144           }
7145
7146         /* Convert the address to binary integer(s) and apply the mask */
7147
7148         sub[maskoffset] = 0;
7149         count = host_aton(sub, binary);
7150         host_mask(count, binary, mask);
7151
7152         /* Convert to masked textual format and add to output. */
7153
7154         yield = string_catn(yield, buffer,
7155           host_nmtoa(count, binary, mask, buffer, '.'));
7156         continue;
7157         }
7158
7159       case EOP_IPV6NORM:
7160       case EOP_IPV6DENORM:
7161         {
7162         int type = string_is_ip_address(sub, NULL);
7163         int binary[4];
7164         uschar buffer[44];
7165
7166         switch (type)
7167           {
7168           case 6:
7169             (void) host_aton(sub, binary);
7170             break;
7171
7172           case 4:       /* convert to IPv4-mapped IPv6 */
7173             binary[0] = binary[1] = 0;
7174             binary[2] = 0x0000ffff;
7175             (void) host_aton(sub, binary+3);
7176             break;
7177
7178           case 0:
7179             expand_string_message =
7180               string_sprintf("\"%s\" is not an IP address", sub);
7181             goto EXPAND_FAILED;
7182           }
7183
7184         yield = string_catn(yield, buffer, c == EOP_IPV6NORM
7185                     ? ipv6_nmtoa(binary, buffer)
7186                     : host_nmtoa(4, binary, -1, buffer, ':')
7187                   );
7188         continue;
7189         }
7190
7191       case EOP_ADDRESS:
7192       case EOP_LOCAL_PART:
7193       case EOP_DOMAIN:
7194         {
7195         uschar * error;
7196         int start, end, domain;
7197         uschar * t = parse_extract_address(sub, &error, &start, &end, &domain,
7198           FALSE);
7199         if (t)
7200           yield = c == EOP_DOMAIN
7201             ? string_cat(yield, t + domain)
7202             : c == EOP_LOCAL_PART && domain > 0
7203             ? string_catn(yield, t, domain - 1 )
7204             : string_cat(yield, t);
7205         continue;
7206         }
7207
7208       case EOP_ADDRESSES:
7209         {
7210         uschar outsep[2] = { ':', '\0' };
7211         uschar *address, *error;
7212         int save_ptr = yield->ptr;
7213         int start, end, domain;  /* Not really used */
7214
7215         while (isspace(*sub)) sub++;
7216         if (*sub == '>')
7217           if (*outsep = *++sub) ++sub;
7218           else
7219             {
7220             expand_string_message = string_sprintf("output separator "
7221               "missing in expanding ${addresses:%s}", --sub);
7222             goto EXPAND_FAILED;
7223             }
7224         f.parse_allow_group = TRUE;
7225
7226         for (;;)
7227           {
7228           uschar * p = parse_find_address_end(sub, FALSE);
7229           uschar saveend = *p;
7230           *p = '\0';
7231           address = parse_extract_address(sub, &error, &start, &end, &domain,
7232             FALSE);
7233           *p = saveend;
7234
7235           /* Add the address to the output list that we are building. This is
7236           done in chunks by searching for the separator character. At the
7237           start, unless we are dealing with the first address of the output
7238           list, add in a space if the new address begins with the separator
7239           character, or is an empty string. */
7240
7241           if (address)
7242             {
7243             if (yield->ptr != save_ptr && address[0] == *outsep)
7244               yield = string_catn(yield, US" ", 1);
7245
7246             for (;;)
7247               {
7248               size_t seglen = Ustrcspn(address, outsep);
7249               yield = string_catn(yield, address, seglen + 1);
7250
7251               /* If we got to the end of the string we output one character
7252               too many. */
7253
7254               if (address[seglen] == '\0') { yield->ptr--; break; }
7255               yield = string_catn(yield, outsep, 1);
7256               address += seglen + 1;
7257               }
7258
7259             /* Output a separator after the string: we will remove the
7260             redundant final one at the end. */
7261
7262             yield = string_catn(yield, outsep, 1);
7263             }
7264
7265           if (saveend == '\0') break;
7266           sub = p + 1;
7267           }
7268
7269         /* If we have generated anything, remove the redundant final
7270         separator. */
7271
7272         if (yield->ptr != save_ptr) yield->ptr--;
7273         f.parse_allow_group = FALSE;
7274         continue;
7275         }
7276
7277
7278       /* quote puts a string in quotes if it is empty or contains anything
7279       other than alphamerics, underscore, dot, or hyphen.
7280
7281       quote_local_part puts a string in quotes if RFC 2821/2822 requires it to
7282       be quoted in order to be a valid local part.
7283
7284       In both cases, newlines and carriage returns are converted into \n and \r
7285       respectively */
7286
7287       case EOP_QUOTE:
7288       case EOP_QUOTE_LOCAL_PART:
7289       if (arg == NULL)
7290         {
7291         BOOL needs_quote = (*sub == 0);      /* TRUE for empty string */
7292         uschar *t = sub - 1;
7293
7294         if (c == EOP_QUOTE)
7295           {
7296           while (!needs_quote && *(++t) != 0)
7297             needs_quote = !isalnum(*t) && !strchr("_-.", *t);
7298           }
7299         else  /* EOP_QUOTE_LOCAL_PART */
7300           {
7301           while (!needs_quote && *(++t) != 0)
7302             needs_quote = !isalnum(*t) &&
7303               strchr("!#$%&'*+-/=?^_`{|}~", *t) == NULL &&
7304               (*t != '.' || t == sub || t[1] == 0);
7305           }
7306
7307         if (needs_quote)
7308           {
7309           yield = string_catn(yield, US"\"", 1);
7310           t = sub - 1;
7311           while (*(++t) != 0)
7312             {
7313             if (*t == '\n')
7314               yield = string_catn(yield, US"\\n", 2);
7315             else if (*t == '\r')
7316               yield = string_catn(yield, US"\\r", 2);
7317             else
7318               {
7319               if (*t == '\\' || *t == '"')
7320                 yield = string_catn(yield, US"\\", 1);
7321               yield = string_catn(yield, t, 1);
7322               }
7323             }
7324           yield = string_catn(yield, US"\"", 1);
7325           }
7326         else yield = string_cat(yield, sub);
7327         continue;
7328         }
7329
7330       /* quote_lookuptype does lookup-specific quoting */
7331
7332       else
7333         {
7334         int n;
7335         uschar *opt = Ustrchr(arg, '_');
7336
7337         if (opt != NULL) *opt++ = 0;
7338
7339         n = search_findtype(arg, Ustrlen(arg));
7340         if (n < 0)
7341           {
7342           expand_string_message = search_error_message;
7343           goto EXPAND_FAILED;
7344           }
7345
7346         if (lookup_list[n]->quote != NULL)
7347           sub = (lookup_list[n]->quote)(sub, opt);
7348         else if (opt != NULL) sub = NULL;
7349
7350         if (sub == NULL)
7351           {
7352           expand_string_message = string_sprintf(
7353             "\"%s\" unrecognized after \"${quote_%s\"",
7354             opt, arg);
7355           goto EXPAND_FAILED;
7356           }
7357
7358         yield = string_cat(yield, sub);
7359         continue;
7360         }
7361
7362       /* rx quote sticks in \ before any non-alphameric character so that
7363       the insertion works in a regular expression. */
7364
7365       case EOP_RXQUOTE:
7366         {
7367         uschar *t = sub - 1;
7368         while (*(++t) != 0)
7369           {
7370           if (!isalnum(*t))
7371             yield = string_catn(yield, US"\\", 1);
7372           yield = string_catn(yield, t, 1);
7373           }
7374         continue;
7375         }
7376
7377       /* RFC 2047 encodes, assuming headers_charset (default ISO 8859-1) as
7378       prescribed by the RFC, if there are characters that need to be encoded */
7379
7380       case EOP_RFC2047:
7381         {
7382         uschar buffer[2048];
7383         yield = string_cat(yield,
7384                             parse_quote_2047(sub, Ustrlen(sub), headers_charset,
7385                               buffer, sizeof(buffer), FALSE));
7386         continue;
7387         }
7388
7389       /* RFC 2047 decode */
7390
7391       case EOP_RFC2047D:
7392         {
7393         int len;
7394         uschar *error;
7395         uschar *decoded = rfc2047_decode(sub, check_rfc2047_length,
7396           headers_charset, '?', &len, &error);
7397         if (error != NULL)
7398           {
7399           expand_string_message = error;
7400           goto EXPAND_FAILED;
7401           }
7402         yield = string_catn(yield, decoded, len);
7403         continue;
7404         }
7405
7406       /* from_utf8 converts UTF-8 to 8859-1, turning non-existent chars into
7407       underscores */
7408
7409       case EOP_FROM_UTF8:
7410         {
7411         while (*sub != 0)
7412           {
7413           int c;
7414           uschar buff[4];
7415           GETUTF8INC(c, sub);
7416           if (c > 255) c = '_';
7417           buff[0] = c;
7418           yield = string_catn(yield, buff, 1);
7419           }
7420         continue;
7421         }
7422
7423           /* replace illegal UTF-8 sequences by replacement character  */
7424
7425       #define UTF8_REPLACEMENT_CHAR US"?"
7426
7427       case EOP_UTF8CLEAN:
7428         {
7429         int seq_len = 0, index = 0;
7430         int bytes_left = 0;
7431         long codepoint = -1;
7432         int complete;
7433         uschar seq_buff[4];                     /* accumulate utf-8 here */
7434
7435         while (*sub != 0)
7436           {
7437           complete = 0;
7438           uschar c = *sub++;
7439
7440           if (bytes_left)
7441             {
7442             if ((c & 0xc0) != 0x80)
7443                     /* wrong continuation byte; invalidate all bytes */
7444               complete = 1; /* error */
7445             else
7446               {
7447               codepoint = (codepoint << 6) | (c & 0x3f);
7448               seq_buff[index++] = c;
7449               if (--bytes_left == 0)            /* codepoint complete */
7450                 if(codepoint > 0x10FFFF)        /* is it too large? */
7451                   complete = -1;        /* error (RFC3629 limit) */
7452                 else
7453                   {             /* finished; output utf-8 sequence */
7454                   yield = string_catn(yield, seq_buff, seq_len);
7455                   index = 0;
7456                   }
7457               }
7458             }
7459           else  /* no bytes left: new sequence */
7460             {
7461             if((c & 0x80) == 0) /* 1-byte sequence, US-ASCII, keep it */
7462               {
7463               yield = string_catn(yield, &c, 1);
7464               continue;
7465               }
7466             if((c & 0xe0) == 0xc0)              /* 2-byte sequence */
7467               {
7468               if(c == 0xc0 || c == 0xc1)        /* 0xc0 and 0xc1 are illegal */
7469                 complete = -1;
7470               else
7471                 {
7472                   bytes_left = 1;
7473                   codepoint = c & 0x1f;
7474                 }
7475               }
7476             else if((c & 0xf0) == 0xe0)         /* 3-byte sequence */
7477               {
7478               bytes_left = 2;
7479               codepoint = c & 0x0f;
7480               }
7481             else if((c & 0xf8) == 0xf0)         /* 4-byte sequence */
7482               {
7483               bytes_left = 3;
7484               codepoint = c & 0x07;
7485               }
7486             else        /* invalid or too long (RFC3629 allows only 4 bytes) */
7487               complete = -1;
7488
7489             seq_buff[index++] = c;
7490             seq_len = bytes_left + 1;
7491             }           /* if(bytes_left) */
7492
7493           if (complete != 0)
7494             {
7495             bytes_left = index = 0;
7496             yield = string_catn(yield, UTF8_REPLACEMENT_CHAR, 1);
7497             }
7498           if ((complete == 1) && ((c & 0x80) == 0))
7499                         /* ASCII character follows incomplete sequence */
7500               yield = string_catn(yield, &c, 1);
7501           }
7502         /* If given a sequence truncated mid-character, we also want to report ?
7503         * Eg, ${length_1:フィル} is one byte, not one character, so we expect
7504         * ${utf8clean:${length_1:フィル}} to yield '?' */
7505         if (bytes_left != 0)
7506           {
7507           yield = string_catn(yield, UTF8_REPLACEMENT_CHAR, 1);
7508           }
7509         continue;
7510         }
7511
7512 #ifdef SUPPORT_I18N
7513       case EOP_UTF8_DOMAIN_TO_ALABEL:
7514         {
7515         uschar * error = NULL;
7516         uschar * s = string_domain_utf8_to_alabel(sub, &error);
7517         if (error)
7518           {
7519           expand_string_message = string_sprintf(
7520             "error converting utf8 (%s) to alabel: %s",
7521             string_printing(sub), error);
7522           goto EXPAND_FAILED;
7523           }
7524         yield = string_cat(yield, s);
7525         continue;
7526         }
7527
7528       case EOP_UTF8_DOMAIN_FROM_ALABEL:
7529         {
7530         uschar * error = NULL;
7531         uschar * s = string_domain_alabel_to_utf8(sub, &error);
7532         if (error)
7533           {
7534           expand_string_message = string_sprintf(
7535             "error converting alabel (%s) to utf8: %s",
7536             string_printing(sub), error);
7537           goto EXPAND_FAILED;
7538           }
7539         yield = string_cat(yield, s);
7540         continue;
7541         }
7542
7543       case EOP_UTF8_LOCALPART_TO_ALABEL:
7544         {
7545         uschar * error = NULL;
7546         uschar * s = string_localpart_utf8_to_alabel(sub, &error);
7547         if (error)
7548           {
7549           expand_string_message = string_sprintf(
7550             "error converting utf8 (%s) to alabel: %s",
7551             string_printing(sub), error);
7552           goto EXPAND_FAILED;
7553           }
7554         yield = string_cat(yield, s);
7555         DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", yield->s);
7556         continue;
7557         }
7558
7559       case EOP_UTF8_LOCALPART_FROM_ALABEL:
7560         {
7561         uschar * error = NULL;
7562         uschar * s = string_localpart_alabel_to_utf8(sub, &error);
7563         if (error)
7564           {
7565           expand_string_message = string_sprintf(
7566             "error converting alabel (%s) to utf8: %s",
7567             string_printing(sub), error);
7568           goto EXPAND_FAILED;
7569           }
7570         yield = string_cat(yield, s);
7571         continue;
7572         }
7573 #endif  /* EXPERIMENTAL_INTERNATIONAL */
7574
7575       /* escape turns all non-printing characters into escape sequences. */
7576
7577       case EOP_ESCAPE:
7578         {
7579         const uschar * t = string_printing(sub);
7580         yield = string_cat(yield, t);
7581         continue;
7582         }
7583
7584       case EOP_ESCAPE8BIT:
7585         {
7586         uschar c;
7587
7588         for (const uschar * s = sub; (c = *s); s++)
7589           yield = c < 127 && c != '\\'
7590             ? string_catn(yield, s, 1)
7591             : string_fmt_append(yield, "\\%03o", c);
7592         continue;
7593         }
7594
7595       /* Handle numeric expression evaluation */
7596
7597       case EOP_EVAL:
7598       case EOP_EVAL10:
7599         {
7600         uschar *save_sub = sub;
7601         uschar *error = NULL;
7602         int_eximarith_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
7603         if (error)
7604           {
7605           expand_string_message = string_sprintf("error in expression "
7606             "evaluation: %s (after processing \"%.*s\")", error,
7607             (int)(sub-save_sub), save_sub);
7608           goto EXPAND_FAILED;
7609           }
7610         yield = string_fmt_append(yield, PR_EXIM_ARITH, n);
7611         continue;
7612         }
7613
7614       /* Handle time period formatting */
7615
7616       case EOP_TIME_EVAL:
7617         {
7618         int n = readconf_readtime(sub, 0, FALSE);
7619         if (n < 0)
7620           {
7621           expand_string_message = string_sprintf("string \"%s\" is not an "
7622             "Exim time interval in \"%s\" operator", sub, name);
7623           goto EXPAND_FAILED;
7624           }
7625         yield = string_fmt_append(yield, "%d", n);
7626         continue;
7627         }
7628
7629       case EOP_TIME_INTERVAL:
7630         {
7631         int n;
7632         uschar *t = read_number(&n, sub);
7633         if (*t != 0) /* Not A Number*/
7634           {
7635           expand_string_message = string_sprintf("string \"%s\" is not a "
7636             "positive number in \"%s\" operator", sub, name);
7637           goto EXPAND_FAILED;
7638           }
7639         t = readconf_printtime(n);
7640         yield = string_cat(yield, t);
7641         continue;
7642         }
7643
7644       /* Convert string to base64 encoding */
7645
7646       case EOP_STR2B64:
7647       case EOP_BASE64:
7648         {
7649 #ifndef DISABLE_TLS
7650         uschar * s = vp && *(void **)vp->value
7651           ? tls_cert_der_b64(*(void **)vp->value)
7652           : b64encode(CUS sub, Ustrlen(sub));
7653 #else
7654         uschar * s = b64encode(CUS sub, Ustrlen(sub));
7655 #endif
7656         yield = string_cat(yield, s);
7657         continue;
7658         }
7659
7660       case EOP_BASE64D:
7661         {
7662         uschar * s;
7663         int len = b64decode(sub, &s);
7664         if (len < 0)
7665           {
7666           expand_string_message = string_sprintf("string \"%s\" is not "
7667             "well-formed for \"%s\" operator", sub, name);
7668           goto EXPAND_FAILED;
7669           }
7670         yield = string_cat(yield, s);
7671         continue;
7672         }
7673
7674       /* strlen returns the length of the string */
7675
7676       case EOP_STRLEN:
7677         yield = string_fmt_append(yield, "%d", Ustrlen(sub));
7678         continue;
7679
7680       /* length_n or l_n takes just the first n characters or the whole string,
7681       whichever is the shorter;
7682
7683       substr_m_n, and s_m_n take n characters from offset m; negative m take
7684       from the end; l_n is synonymous with s_0_n. If n is omitted in substr it
7685       takes the rest, either to the right or to the left.
7686
7687       hash_n or h_n makes a hash of length n from the string, yielding n
7688       characters from the set a-z; hash_n_m makes a hash of length n, but
7689       uses m characters from the set a-zA-Z0-9.
7690
7691       nhash_n returns a single number between 0 and n-1 (in text form), while
7692       nhash_n_m returns a div/mod hash as two numbers "a/b". The first lies
7693       between 0 and n-1 and the second between 0 and m-1. */
7694
7695       case EOP_LENGTH:
7696       case EOP_L:
7697       case EOP_SUBSTR:
7698       case EOP_S:
7699       case EOP_HASH:
7700       case EOP_H:
7701       case EOP_NHASH:
7702       case EOP_NH:
7703         {
7704         int sign = 1;
7705         int value1 = 0;
7706         int value2 = -1;
7707         int *pn;
7708         int len;
7709         uschar *ret;
7710
7711         if (!arg)
7712           {
7713           expand_string_message = string_sprintf("missing values after %s",
7714             name);
7715           goto EXPAND_FAILED;
7716           }
7717
7718         /* "length" has only one argument, effectively being synonymous with
7719         substr_0_n. */
7720
7721         if (c == EOP_LENGTH || c == EOP_L)
7722           {
7723           pn = &value2;
7724           value2 = 0;
7725           }
7726
7727         /* The others have one or two arguments; for "substr" the first may be
7728         negative. The second being negative means "not supplied". */
7729
7730         else
7731           {
7732           pn = &value1;
7733           if (name[0] == 's' && *arg == '-') { sign = -1; arg++; }
7734           }
7735
7736         /* Read up to two numbers, separated by underscores */
7737
7738         ret = arg;
7739         while (*arg != 0)
7740           {
7741           if (arg != ret && *arg == '_' && pn == &value1)
7742             {
7743             pn = &value2;
7744             value2 = 0;
7745             if (arg[1] != 0) arg++;
7746             }
7747           else if (!isdigit(*arg))
7748             {
7749             expand_string_message =
7750               string_sprintf("non-digit after underscore in \"%s\"", name);
7751             goto EXPAND_FAILED;
7752             }
7753           else *pn = (*pn)*10 + *arg++ - '0';
7754           }
7755         value1 *= sign;
7756
7757         /* Perform the required operation */
7758
7759         ret =
7760           (c == EOP_HASH || c == EOP_H)?
7761              compute_hash(sub, value1, value2, &len) :
7762           (c == EOP_NHASH || c == EOP_NH)?
7763              compute_nhash(sub, value1, value2, &len) :
7764              extract_substr(sub, value1, value2, &len);
7765
7766         if (ret == NULL) goto EXPAND_FAILED;
7767         yield = string_catn(yield, ret, len);
7768         continue;
7769         }
7770
7771       /* Stat a path */
7772
7773       case EOP_STAT:
7774         {
7775         uschar smode[12];
7776         uschar **modetable[3];
7777         mode_t mode;
7778         struct stat st;
7779
7780         if (expand_forbid & RDO_EXISTS)
7781           {
7782           expand_string_message = US"Use of the stat() expansion is not permitted";
7783           goto EXPAND_FAILED;
7784           }
7785
7786         if (stat(CS sub, &st) < 0)
7787           {
7788           expand_string_message = string_sprintf("stat(%s) failed: %s",
7789             sub, strerror(errno));
7790           goto EXPAND_FAILED;
7791           }
7792         mode = st.st_mode;
7793         switch (mode & S_IFMT)
7794           {
7795           case S_IFIFO: smode[0] = 'p'; break;
7796           case S_IFCHR: smode[0] = 'c'; break;
7797           case S_IFDIR: smode[0] = 'd'; break;
7798           case S_IFBLK: smode[0] = 'b'; break;
7799           case S_IFREG: smode[0] = '-'; break;
7800           default: smode[0] = '?'; break;
7801           }
7802
7803         modetable[0] = ((mode & 01000) == 0)? mtable_normal : mtable_sticky;
7804         modetable[1] = ((mode & 02000) == 0)? mtable_normal : mtable_setid;
7805         modetable[2] = ((mode & 04000) == 0)? mtable_normal : mtable_setid;
7806
7807         for (int i = 0; i < 3; i++)
7808           {
7809           memcpy(CS(smode + 7 - i*3), CS(modetable[i][mode & 7]), 3);
7810           mode >>= 3;
7811           }
7812
7813         smode[10] = 0;
7814         yield = string_fmt_append(yield,
7815           "mode=%04lo smode=%s inode=%ld device=%ld links=%ld "
7816           "uid=%ld gid=%ld size=" OFF_T_FMT " atime=%ld mtime=%ld ctime=%ld",
7817           (long)(st.st_mode & 077777), smode, (long)st.st_ino,
7818           (long)st.st_dev, (long)st.st_nlink, (long)st.st_uid,
7819           (long)st.st_gid, st.st_size, (long)st.st_atime,
7820           (long)st.st_mtime, (long)st.st_ctime);
7821         continue;
7822         }
7823
7824       /* vaguely random number less than N */
7825
7826       case EOP_RANDINT:
7827         {
7828         int_eximarith_t max = expanded_string_integer(sub, TRUE);
7829
7830         if (expand_string_message)
7831           goto EXPAND_FAILED;
7832         yield = string_fmt_append(yield, "%d", vaguely_random_number((int)max));
7833         continue;
7834         }
7835
7836       /* Reverse IP, including IPv6 to dotted-nibble */
7837
7838       case EOP_REVERSE_IP:
7839         {
7840         int family, maskptr;
7841         uschar reversed[128];
7842
7843         family = string_is_ip_address(sub, &maskptr);
7844         if (family == 0)
7845           {
7846           expand_string_message = string_sprintf(
7847               "reverse_ip() not given an IP address [%s]", sub);
7848           goto EXPAND_FAILED;
7849           }
7850         invert_address(reversed, sub);
7851         yield = string_cat(yield, reversed);
7852         continue;
7853         }
7854
7855       /* Unknown operator */
7856
7857       default:
7858         expand_string_message =
7859           string_sprintf("unknown expansion operator \"%s\"", name);
7860         goto EXPAND_FAILED;
7861       }
7862     }
7863
7864   /* Handle a plain name. If this is the first thing in the expansion, release
7865   the pre-allocated buffer. If the result data is known to be in a new buffer,
7866   newsize will be set to the size of that buffer, and we can just point at that
7867   store instead of copying. Many expansion strings contain just one reference,
7868   so this is a useful optimization, especially for humungous headers
7869   ($message_headers). */
7870                                                 /*{*/
7871   if (*s++ == '}')
7872     {
7873     int len;
7874     int newsize = 0;
7875     gstring * g = NULL;
7876
7877     if (!yield)
7878       g = store_get(sizeof(gstring));
7879     else if (yield->ptr == 0)
7880       {
7881       if (resetok) store_reset(yield);
7882       yield = NULL;
7883       g = store_get(sizeof(gstring));   /* alloc _before_ calling find_variable() */
7884       }
7885     if (!(value = find_variable(name, FALSE, skipping, &newsize)))
7886       {
7887       expand_string_message =
7888         string_sprintf("unknown variable in \"${%s}\"", name);
7889       check_variable_error_message(name);
7890       goto EXPAND_FAILED;
7891       }
7892     len = Ustrlen(value);
7893     if (!yield && newsize)
7894       {
7895       yield = g;
7896       yield->size = newsize;
7897       yield->ptr = len;
7898       yield->s = value;
7899       }
7900     else
7901       yield = string_catn(yield, value, len);
7902     continue;
7903     }
7904
7905   /* Else there's something wrong */
7906
7907   expand_string_message =
7908     string_sprintf("\"${%s\" is not a known operator (or a } is missing "
7909     "in a variable reference)", name);
7910   goto EXPAND_FAILED;
7911   }
7912
7913 /* If we hit the end of the string when ket_ends is set, there is a missing
7914 terminating brace. */
7915
7916 if (ket_ends && *s == 0)
7917   {
7918   expand_string_message = malformed_header
7919     ? US"missing } at end of string - could be header name not terminated by colon"
7920     : US"missing } at end of string";
7921   goto EXPAND_FAILED;
7922   }
7923
7924 /* Expansion succeeded; yield may still be NULL here if nothing was actually
7925 added to the string. If so, set up an empty string. Add a terminating zero. If
7926 left != NULL, return a pointer to the terminator. */
7927
7928 if (!yield)
7929   yield = string_get(1);
7930 (void) string_from_gstring(yield);
7931 if (left) *left = s;
7932
7933 /* Any stacking store that was used above the final string is no longer needed.
7934 In many cases the final string will be the first one that was got and so there
7935 will be optimal store usage. */
7936
7937 if (resetok) store_reset(yield->s + (yield->size = yield->ptr + 1));
7938 else if (resetok_p) *resetok_p = FALSE;
7939
7940 DEBUG(D_expand)
7941   DEBUG(D_noutf8)
7942     {
7943     debug_printf_indent("|--expanding: %.*s\n", (int)(s - string), string);
7944     debug_printf_indent("%sresult: %s\n",
7945       skipping ? "|-----" : "\\_____", yield->s);
7946     if (skipping)
7947       debug_printf_indent("\\___skipping: result is not used\n");
7948     }
7949   else
7950     {
7951     debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
7952       "expanding: %.*s\n",
7953       (int)(s - string), string);
7954     debug_printf_indent("%s"
7955       UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
7956       "result: %s\n",
7957       skipping ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
7958       yield->s);
7959     if (skipping)
7960       debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
7961         "skipping: result is not used\n");
7962     }
7963 expand_level--;
7964 return yield->s;
7965
7966 /* This is the failure exit: easiest to program with a goto. We still need
7967 to update the pointer to the terminator, for cases of nested calls with "fail".
7968 */
7969
7970 EXPAND_FAILED_CURLY:
7971 if (malformed_header)
7972   expand_string_message =
7973     US"missing or misplaced { or } - could be header name not terminated by colon";
7974
7975 else if (!expand_string_message || !*expand_string_message)
7976   expand_string_message = US"missing or misplaced { or }";
7977
7978 /* At one point, Exim reset the store to yield (if yield was not NULL), but
7979 that is a bad idea, because expand_string_message is in dynamic store. */
7980
7981 EXPAND_FAILED:
7982 if (left) *left = s;
7983 DEBUG(D_expand)
7984   DEBUG(D_noutf8)
7985     {
7986     debug_printf_indent("|failed to expand: %s\n", string);
7987     debug_printf_indent("%serror message: %s\n",
7988       f.expand_string_forcedfail ? "|---" : "\\___", expand_string_message);
7989     if (f.expand_string_forcedfail)
7990       debug_printf_indent("\\failure was forced\n");
7991     }
7992   else
7993     {
7994     debug_printf_indent(UTF8_VERT_RIGHT "failed to expand: %s\n",
7995       string);
7996     debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
7997       "error message: %s\n",
7998       f.expand_string_forcedfail ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
7999       expand_string_message);
8000     if (f.expand_string_forcedfail)
8001       debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n");
8002     }
8003 if (resetok_p && !resetok) *resetok_p = FALSE;
8004 expand_level--;
8005 return NULL;
8006 }
8007
8008
8009 /* This is the external function call. Do a quick check for any expansion
8010 metacharacters, and if there are none, just return the input string.
8011
8012 Argument: the string to be expanded
8013 Returns:  the expanded string, or NULL if expansion failed; if failure was
8014           due to a lookup deferring, search_find_defer will be TRUE
8015 */
8016
8017 const uschar *
8018 expand_cstring(const uschar * string)
8019 {
8020 if (Ustrpbrk(string, "$\\") != NULL)
8021   {
8022   int old_pool = store_pool;
8023   uschar * s;
8024
8025   f.search_find_defer = FALSE;
8026   malformed_header = FALSE;
8027   store_pool = POOL_MAIN;
8028     s = expand_string_internal(string, FALSE, NULL, FALSE, TRUE, NULL);
8029   store_pool = old_pool;
8030   return s;
8031   }
8032 return string;
8033 }
8034
8035
8036 uschar *
8037 expand_string(uschar * string)
8038 {
8039 return US expand_cstring(CUS string);
8040 }
8041
8042
8043
8044
8045
8046 /*************************************************
8047 *              Expand and copy                   *
8048 *************************************************/
8049
8050 /* Now and again we want to expand a string and be sure that the result is in a
8051 new bit of store. This function does that.
8052 Since we know it has been copied, the de-const cast is safe.
8053
8054 Argument: the string to be expanded
8055 Returns:  the expanded string, always in a new bit of store, or NULL
8056 */
8057
8058 uschar *
8059 expand_string_copy(const uschar *string)
8060 {
8061 const uschar *yield = expand_cstring(string);
8062 if (yield == string) yield = string_copy(string);
8063 return US yield;
8064 }
8065
8066
8067
8068 /*************************************************
8069 *        Expand and interpret as an integer      *
8070 *************************************************/
8071
8072 /* Expand a string, and convert the result into an integer.
8073
8074 Arguments:
8075   string  the string to be expanded
8076   isplus  TRUE if a non-negative number is expected
8077
8078 Returns:  the integer value, or
8079           -1 for an expansion error               ) in both cases, message in
8080           -2 for an integer interpretation error  ) expand_string_message
8081           expand_string_message is set NULL for an OK integer
8082 */
8083
8084 int_eximarith_t
8085 expand_string_integer(uschar *string, BOOL isplus)
8086 {
8087 return expanded_string_integer(expand_string(string), isplus);
8088 }
8089
8090
8091 /*************************************************
8092  *         Interpret string as an integer        *
8093  *************************************************/
8094
8095 /* Convert a string (that has already been expanded) into an integer.
8096
8097 This function is used inside the expansion code.
8098
8099 Arguments:
8100   s       the string to be expanded
8101   isplus  TRUE if a non-negative number is expected
8102
8103 Returns:  the integer value, or
8104           -1 if string is NULL (which implies an expansion error)
8105           -2 for an integer interpretation error
8106           expand_string_message is set NULL for an OK integer
8107 */
8108
8109 static int_eximarith_t
8110 expanded_string_integer(const uschar *s, BOOL isplus)
8111 {
8112 int_eximarith_t value;
8113 uschar *msg = US"invalid integer \"%s\"";
8114 uschar *endptr;
8115
8116 /* If expansion failed, expand_string_message will be set. */
8117
8118 if (s == NULL) return -1;
8119
8120 /* On an overflow, strtol() returns LONG_MAX or LONG_MIN, and sets errno
8121 to ERANGE. When there isn't an overflow, errno is not changed, at least on some
8122 systems, so we set it zero ourselves. */
8123
8124 errno = 0;
8125 expand_string_message = NULL;               /* Indicates no error */
8126
8127 /* Before Exim 4.64, strings consisting entirely of whitespace compared
8128 equal to 0.  Unfortunately, people actually relied upon that, so preserve
8129 the behaviour explicitly.  Stripping leading whitespace is a harmless
8130 noop change since strtol skips it anyway (provided that there is a number
8131 to find at all). */
8132 if (isspace(*s))
8133   {
8134   while (isspace(*s)) ++s;
8135   if (*s == '\0')
8136     {
8137       DEBUG(D_expand)
8138        debug_printf_indent("treating blank string as number 0\n");
8139       return 0;
8140     }
8141   }
8142
8143 value = strtoll(CS s, CSS &endptr, 10);
8144
8145 if (endptr == s)
8146   {
8147   msg = US"integer expected but \"%s\" found";
8148   }
8149 else if (value < 0 && isplus)
8150   {
8151   msg = US"non-negative integer expected but \"%s\" found";
8152   }
8153 else
8154   {
8155   switch (tolower(*endptr))
8156     {
8157     default:
8158       break;
8159     case 'k':
8160       if (value > EXIM_ARITH_MAX/1024 || value < EXIM_ARITH_MIN/1024) errno = ERANGE;
8161       else value *= 1024;
8162       endptr++;
8163       break;
8164     case 'm':
8165       if (value > EXIM_ARITH_MAX/(1024*1024) || value < EXIM_ARITH_MIN/(1024*1024)) errno = ERANGE;
8166       else value *= 1024*1024;
8167       endptr++;
8168       break;
8169     case 'g':
8170       if (value > EXIM_ARITH_MAX/(1024*1024*1024) || value < EXIM_ARITH_MIN/(1024*1024*1024)) errno = ERANGE;
8171       else value *= 1024*1024*1024;
8172       endptr++;
8173       break;
8174     }
8175   if (errno == ERANGE)
8176     msg = US"absolute value of integer \"%s\" is too large (overflow)";
8177   else
8178     {
8179     while (isspace(*endptr)) endptr++;
8180     if (*endptr == 0) return value;
8181     }
8182   }
8183
8184 expand_string_message = string_sprintf(CS msg, s);
8185 return -2;
8186 }
8187
8188
8189 /* These values are usually fixed boolean values, but they are permitted to be
8190 expanded strings.
8191
8192 Arguments:
8193   addr       address being routed
8194   mtype      the module type
8195   mname      the module name
8196   dbg_opt    debug selectors
8197   oname      the option name
8198   bvalue     the router's boolean value
8199   svalue     the router's string value
8200   rvalue     where to put the returned value
8201
8202 Returns:     OK     value placed in rvalue
8203              DEFER  expansion failed
8204 */
8205
8206 int
8207 exp_bool(address_item *addr,
8208   uschar *mtype, uschar *mname, unsigned dbg_opt,
8209   uschar *oname, BOOL bvalue,
8210   uschar *svalue, BOOL *rvalue)
8211 {
8212 uschar *expanded;
8213 if (svalue == NULL) { *rvalue = bvalue; return OK; }
8214
8215 expanded = expand_string(svalue);
8216 if (expanded == NULL)
8217   {
8218   if (f.expand_string_forcedfail)
8219     {
8220     DEBUG(dbg_opt) debug_printf("expansion of \"%s\" forced failure\n", oname);
8221     *rvalue = bvalue;
8222     return OK;
8223     }
8224   addr->message = string_sprintf("failed to expand \"%s\" in %s %s: %s",
8225       oname, mname, mtype, expand_string_message);
8226   DEBUG(dbg_opt) debug_printf("%s\n", addr->message);
8227   return DEFER;
8228   }
8229
8230 DEBUG(dbg_opt) debug_printf("expansion of \"%s\" yields \"%s\"\n", oname,
8231   expanded);
8232
8233 if (strcmpic(expanded, US"true") == 0 || strcmpic(expanded, US"yes") == 0)
8234   *rvalue = TRUE;
8235 else if (strcmpic(expanded, US"false") == 0 || strcmpic(expanded, US"no") == 0)
8236   *rvalue = FALSE;
8237 else
8238   {
8239   addr->message = string_sprintf("\"%s\" is not a valid value for the "
8240     "\"%s\" option in the %s %s", expanded, oname, mname, mtype);
8241   return DEFER;
8242   }
8243
8244 return OK;
8245 }
8246
8247
8248
8249 /* Avoid potentially exposing a password in a string about to be logged */
8250
8251 uschar *
8252 expand_hide_passwords(uschar * s)
8253 {
8254 return (  (  Ustrstr(s, "failed to expand") != NULL
8255           || Ustrstr(s, "expansion of ")    != NULL
8256           )
8257        && (  Ustrstr(s, "mysql")   != NULL
8258           || Ustrstr(s, "pgsql")   != NULL
8259           || Ustrstr(s, "redis")   != NULL
8260           || Ustrstr(s, "sqlite")  != NULL
8261           || Ustrstr(s, "ldap:")   != NULL
8262           || Ustrstr(s, "ldaps:")  != NULL
8263           || Ustrstr(s, "ldapi:")  != NULL
8264           || Ustrstr(s, "ldapdn:") != NULL
8265           || Ustrstr(s, "ldapm:")  != NULL
8266        )  )
8267   ? US"Temporary internal error" : s;
8268 }
8269
8270
8271 /* Read given named file into big_buffer.  Use for keying material etc.
8272 The content will have an ascii NUL appended.
8273
8274 Arguments:
8275  filename       as it says
8276
8277 Return:  pointer to buffer, or NULL on error.
8278 */
8279
8280 uschar *
8281 expand_file_big_buffer(const uschar * filename)
8282 {
8283 int fd, off = 0, len;
8284
8285 if ((fd = open(CS filename, O_RDONLY)) < 0)
8286   {
8287   log_write(0, LOG_MAIN | LOG_PANIC, "unable to open file for reading: %s",
8288              filename);
8289   return NULL;
8290   }
8291
8292 do
8293   {
8294   if ((len = read(fd, big_buffer + off, big_buffer_size - 2 - off)) < 0)
8295     {
8296     (void) close(fd);
8297     log_write(0, LOG_MAIN|LOG_PANIC, "unable to read file: %s", filename);
8298     return NULL;
8299     }
8300   off += len;
8301   }
8302 while (len > 0);
8303
8304 (void) close(fd);
8305 big_buffer[off] = '\0';
8306 return big_buffer;
8307 }
8308
8309
8310
8311 /*************************************************
8312 * Error-checking for testsuite                   *
8313 *************************************************/
8314 typedef struct {
8315   uschar *      region_start;
8316   uschar *      region_end;
8317   const uschar *var_name;
8318   const uschar *var_data;
8319 } err_ctx;
8320
8321 static void
8322 assert_variable_notin(uschar * var_name, uschar * var_data, void * ctx)
8323 {
8324 err_ctx * e = ctx;
8325 if (var_data >= e->region_start  &&  var_data < e->region_end)
8326   {
8327   e->var_name = CUS var_name;
8328   e->var_data = CUS var_data;
8329   }
8330 }
8331
8332 void
8333 assert_no_variables(void * ptr, int len, const char * filename, int linenumber)
8334 {
8335 err_ctx e = { .region_start = ptr, .region_end = US ptr + len,
8336               .var_name = NULL, .var_data = NULL };
8337
8338 /* check acl_ variables */
8339 tree_walk(acl_var_c, assert_variable_notin, &e);
8340 tree_walk(acl_var_m, assert_variable_notin, &e);
8341
8342 /* check auth<n> variables */
8343 for (int i = 0; i < AUTH_VARS; i++) if (auth_vars[i])
8344   assert_variable_notin(US"auth<n>", auth_vars[i], &e);
8345
8346 /* check regex<n> variables */
8347 for (int i = 0; i < REGEX_VARS; i++) if (regex_vars[i])
8348   assert_variable_notin(US"regex<n>", regex_vars[i], &e);
8349
8350 /* check known-name variables */
8351 for (var_entry * v = var_table; v < var_table + var_table_size; v++)
8352   if (v->type == vtype_stringptr)
8353     assert_variable_notin(US v->name, *(USS v->value), &e);
8354
8355 /* check dns and address trees */
8356 tree_walk(tree_dns_fails,     assert_variable_notin, &e);
8357 tree_walk(tree_duplicates,    assert_variable_notin, &e);
8358 tree_walk(tree_nonrecipients, assert_variable_notin, &e);
8359 tree_walk(tree_unusable,      assert_variable_notin, &e);
8360
8361 if (e.var_name)
8362   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
8363     "live variable '%s' destroyed by reset_store at %s:%d\n- value '%.64s'",
8364     e.var_name, filename, linenumber, e.var_data);
8365 }
8366
8367
8368
8369 /*************************************************
8370 **************************************************
8371 *             Stand-alone test program           *
8372 **************************************************
8373 *************************************************/
8374
8375 #ifdef STAND_ALONE
8376
8377
8378 BOOL
8379 regex_match_and_setup(const pcre *re, uschar *subject, int options, int setup)
8380 {
8381 int ovector[3*(EXPAND_MAXN+1)];
8382 int n = pcre_exec(re, NULL, subject, Ustrlen(subject), 0, PCRE_EOPT|options,
8383   ovector, nelem(ovector));
8384 BOOL yield = n >= 0;
8385 if (n == 0) n = EXPAND_MAXN + 1;
8386 if (yield)
8387   {
8388   expand_nmax = setup < 0 ? 0 : setup + 1;
8389   for (int nn = setup < 0 ? 0 : 2; nn < n*2; nn += 2)
8390     {
8391     expand_nstring[expand_nmax] = subject + ovector[nn];
8392     expand_nlength[expand_nmax++] = ovector[nn+1] - ovector[nn];
8393     }
8394   expand_nmax--;
8395   }
8396 return yield;
8397 }
8398
8399
8400 int main(int argc, uschar **argv)
8401 {
8402 uschar buffer[1024];
8403
8404 debug_selector = D_v;
8405 debug_file = stderr;
8406 debug_fd = fileno(debug_file);
8407 big_buffer = malloc(big_buffer_size);
8408
8409 for (int i = 1; i < argc; i++)
8410   {
8411   if (argv[i][0] == '+')
8412     {
8413     debug_trace_memory = 2;
8414     argv[i]++;
8415     }
8416   if (isdigit(argv[i][0]))
8417     debug_selector = Ustrtol(argv[i], NULL, 0);
8418   else
8419     if (Ustrspn(argv[i], "abcdefghijklmnopqrtsuvwxyz0123456789-.:/") ==
8420         Ustrlen(argv[i]))
8421       {
8422 #ifdef LOOKUP_LDAP
8423       eldap_default_servers = argv[i];
8424 #endif
8425 #ifdef LOOKUP_MYSQL
8426       mysql_servers = argv[i];
8427 #endif
8428 #ifdef LOOKUP_PGSQL
8429       pgsql_servers = argv[i];
8430 #endif
8431 #ifdef LOOKUP_REDIS
8432       redis_servers = argv[i];
8433 #endif
8434       }
8435 #ifdef EXIM_PERL
8436   else opt_perl_startup = argv[i];
8437 #endif
8438   }
8439
8440 printf("Testing string expansion: debug_level = %d\n\n", debug_level);
8441
8442 expand_nstring[1] = US"string 1....";
8443 expand_nlength[1] = 8;
8444 expand_nmax = 1;
8445
8446 #ifdef EXIM_PERL
8447 if (opt_perl_startup != NULL)
8448   {
8449   uschar *errstr;
8450   printf("Starting Perl interpreter\n");
8451   errstr = init_perl(opt_perl_startup);
8452   if (errstr != NULL)
8453     {
8454     printf("** error in perl_startup code: %s\n", errstr);
8455     return EXIT_FAILURE;
8456     }
8457   }
8458 #endif /* EXIM_PERL */
8459
8460 while (fgets(buffer, sizeof(buffer), stdin) != NULL)
8461   {
8462   void *reset_point = store_get(0);
8463   uschar *yield = expand_string(buffer);
8464   if (yield != NULL)
8465     {
8466     printf("%s\n", yield);
8467     store_reset(reset_point);
8468     }
8469   else
8470     {
8471     if (f.search_find_defer) printf("search_find deferred\n");
8472     printf("Failed: %s\n", expand_string_message);
8473     if (f.expand_string_forcedfail) printf("Forced failure\n");
8474     printf("\n");
8475     }
8476   }
8477
8478 search_tidyup();
8479
8480 return 0;
8481 }
8482
8483 #endif
8484
8485 /* vi: aw ai sw=2
8486 */
8487 /* End of expand.c */