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