Copyright updates:
[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 EXPERIMENTAL_SRS_NATIVE
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 EXPERIMENTAL_SRS_NATIVE
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 EXPERIMENTAL_SRS_NATIVE
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 EXPERIMENTAL_SRS_NATIVE
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 { "local_part_verified", vtype_stringptr, &deliver_localpart_verified },
599 #ifdef HAVE_LOCAL_SCAN
600 { "local_scan_data", vtype_stringptr, &local_scan_data },
601 #endif
602 { "local_user_gid", vtype_gid, &local_user_gid },
603 { "local_user_uid", vtype_uid, &local_user_uid },
604 { "localhost_number", vtype_int, &host_number },
605 { "log_inodes", vtype_pinodes, (void *)FALSE },
606 { "log_space", vtype_pspace, (void *)FALSE },
607 { "lookup_dnssec_authenticated",vtype_stringptr,&lookup_dnssec_authenticated},
608 { "mailstore_basename", vtype_stringptr, &mailstore_basename },
609 #ifdef WITH_CONTENT_SCAN
610 { "malware_name", vtype_stringptr, &malware_name },
611 #endif
612 { "max_received_linelength", vtype_int, &max_received_linelength },
613 { "message_age", vtype_int, &message_age },
614 { "message_body", vtype_msgbody, &message_body },
615 { "message_body_end", vtype_msgbody_end, &message_body_end },
616 { "message_body_size", vtype_int, &message_body_size },
617 { "message_exim_id", vtype_stringptr, &message_id },
618 { "message_headers", vtype_msgheaders, NULL },
619 { "message_headers_raw", vtype_msgheaders_raw, NULL },
620 { "message_id", vtype_stringptr, &message_id },
621 { "message_linecount", vtype_int, &message_linecount },
622 { "message_size", vtype_int, &message_size },
623 #ifdef SUPPORT_I18N
624 { "message_smtputf8", vtype_bool, &message_smtputf8 },
625 #endif
626 #ifdef WITH_CONTENT_SCAN
627 { "mime_anomaly_level", vtype_int, &mime_anomaly_level },
628 { "mime_anomaly_text", vtype_stringptr, &mime_anomaly_text },
629 { "mime_boundary", vtype_stringptr, &mime_boundary },
630 { "mime_charset", vtype_stringptr, &mime_charset },
631 { "mime_content_description", vtype_stringptr, &mime_content_description },
632 { "mime_content_disposition", vtype_stringptr, &mime_content_disposition },
633 { "mime_content_id", vtype_stringptr, &mime_content_id },
634 { "mime_content_size", vtype_int, &mime_content_size },
635 { "mime_content_transfer_encoding",vtype_stringptr, &mime_content_transfer_encoding },
636 { "mime_content_type", vtype_stringptr, &mime_content_type },
637 { "mime_decoded_filename", vtype_stringptr, &mime_decoded_filename },
638 { "mime_filename", vtype_stringptr, &mime_filename },
639 { "mime_is_coverletter", vtype_int, &mime_is_coverletter },
640 { "mime_is_multipart", vtype_int, &mime_is_multipart },
641 { "mime_is_rfc822", vtype_int, &mime_is_rfc822 },
642 { "mime_part_count", vtype_int, &mime_part_count },
643 #endif
644 { "n0", vtype_filter_int, &filter_n[0] },
645 { "n1", vtype_filter_int, &filter_n[1] },
646 { "n2", vtype_filter_int, &filter_n[2] },
647 { "n3", vtype_filter_int, &filter_n[3] },
648 { "n4", vtype_filter_int, &filter_n[4] },
649 { "n5", vtype_filter_int, &filter_n[5] },
650 { "n6", vtype_filter_int, &filter_n[6] },
651 { "n7", vtype_filter_int, &filter_n[7] },
652 { "n8", vtype_filter_int, &filter_n[8] },
653 { "n9", vtype_filter_int, &filter_n[9] },
654 { "original_domain", vtype_stringptr, &deliver_domain_orig },
655 { "original_local_part", vtype_stringptr, &deliver_localpart_orig },
656 { "originator_gid", vtype_gid, &originator_gid },
657 { "originator_uid", vtype_uid, &originator_uid },
658 { "parent_domain", vtype_stringptr, &deliver_domain_parent },
659 { "parent_local_part", vtype_stringptr, &deliver_localpart_parent },
660 { "pid", vtype_pid, NULL },
661 #ifndef DISABLE_PRDR
662 { "prdr_requested", vtype_bool, &prdr_requested },
663 #endif
664 { "primary_hostname", vtype_stringptr, &primary_hostname },
665 #if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
666 { "proxy_external_address",vtype_stringptr, &proxy_external_address },
667 { "proxy_external_port", vtype_int, &proxy_external_port },
668 { "proxy_local_address", vtype_stringptr, &proxy_local_address },
669 { "proxy_local_port", vtype_int, &proxy_local_port },
670 { "proxy_session", vtype_bool, &proxy_session },
671 #endif
672 { "prvscheck_address", vtype_stringptr, &prvscheck_address },
673 { "prvscheck_keynum", vtype_stringptr, &prvscheck_keynum },
674 { "prvscheck_result", vtype_stringptr, &prvscheck_result },
675 { "qualify_domain", vtype_stringptr, &qualify_domain_sender },
676 { "qualify_recipient", vtype_stringptr, &qualify_domain_recipient },
677 { "queue_name", vtype_stringptr, &queue_name },
678 { "queue_size", vtype_string_func, &fn_queue_size },
679 { "rcpt_count", vtype_int, &rcpt_count },
680 { "rcpt_defer_count", vtype_int, &rcpt_defer_count },
681 { "rcpt_fail_count", vtype_int, &rcpt_fail_count },
682 { "received_count", vtype_int, &received_count },
683 { "received_for", vtype_stringptr, &received_for },
684 { "received_ip_address", vtype_stringptr, &interface_address },
685 { "received_port", vtype_int, &interface_port },
686 { "received_protocol", vtype_stringptr, &received_protocol },
687 { "received_time", vtype_int, &received_time.tv_sec },
688 { "recipient_data", vtype_stringptr, &recipient_data },
689 { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
690 { "recipients", vtype_string_func, (void *) &fn_recipients },
691 { "recipients_count", vtype_int, &recipients_count },
692 #ifdef WITH_CONTENT_SCAN
693 { "regex_match_string", vtype_stringptr, &regex_match_string },
694 #endif
695 { "reply_address", vtype_reply, NULL },
696 { "return_path", vtype_stringptr, &return_path },
697 { "return_size_limit", vtype_int, &bounce_return_size_limit },
698 { "router_name", vtype_stringptr, &router_name },
699 { "runrc", vtype_int, &runrc },
700 { "self_hostname", vtype_stringptr, &self_hostname },
701 { "sender_address", vtype_stringptr, &sender_address },
702 { "sender_address_data", vtype_stringptr, &sender_address_data },
703 { "sender_address_domain", vtype_domain, &sender_address },
704 { "sender_address_local_part", vtype_localpart, &sender_address },
705 { "sender_data", vtype_stringptr, &sender_data },
706 { "sender_fullhost", vtype_stringptr, &sender_fullhost },
707 { "sender_helo_dnssec", vtype_bool, &sender_helo_dnssec },
708 { "sender_helo_name", vtype_stringptr, &sender_helo_name },
709 { "sender_host_address", vtype_stringptr, &sender_host_address },
710 { "sender_host_authenticated",vtype_stringptr, &sender_host_authenticated },
711 { "sender_host_dnssec", vtype_bool, &sender_host_dnssec },
712 { "sender_host_name", vtype_host_lookup, NULL },
713 { "sender_host_port", vtype_int, &sender_host_port },
714 { "sender_ident", vtype_stringptr, &sender_ident },
715 { "sender_rate", vtype_stringptr, &sender_rate },
716 { "sender_rate_limit", vtype_stringptr, &sender_rate_limit },
717 { "sender_rate_period", vtype_stringptr, &sender_rate_period },
718 { "sender_rcvhost", vtype_stringptr, &sender_rcvhost },
719 { "sender_verify_failure",vtype_stringptr, &sender_verify_failure },
720 { "sending_ip_address", vtype_stringptr, &sending_ip_address },
721 { "sending_port", vtype_int, &sending_port },
722 { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname },
723 { "smtp_command", vtype_stringptr, &smtp_cmd_buffer },
724 { "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument },
725 { "smtp_command_history", vtype_string_func, (void *) &smtp_cmd_hist },
726 { "smtp_count_at_connection_start", vtype_int, &smtp_accept_count },
727 { "smtp_notquit_reason", vtype_stringptr, &smtp_notquit_reason },
728 { "sn0", vtype_filter_int, &filter_sn[0] },
729 { "sn1", vtype_filter_int, &filter_sn[1] },
730 { "sn2", vtype_filter_int, &filter_sn[2] },
731 { "sn3", vtype_filter_int, &filter_sn[3] },
732 { "sn4", vtype_filter_int, &filter_sn[4] },
733 { "sn5", vtype_filter_int, &filter_sn[5] },
734 { "sn6", vtype_filter_int, &filter_sn[6] },
735 { "sn7", vtype_filter_int, &filter_sn[7] },
736 { "sn8", vtype_filter_int, &filter_sn[8] },
737 { "sn9", vtype_filter_int, &filter_sn[9] },
738 #ifdef WITH_CONTENT_SCAN
739 { "spam_action", vtype_stringptr, &spam_action },
740 { "spam_bar", vtype_stringptr, &spam_bar },
741 { "spam_report", vtype_stringptr, &spam_report },
742 { "spam_score", vtype_stringptr, &spam_score },
743 { "spam_score_int", vtype_stringptr, &spam_score_int },
744 #endif
745 #ifdef SUPPORT_SPF
746 { "spf_guess", vtype_stringptr, &spf_guess },
747 { "spf_header_comment", vtype_stringptr, &spf_header_comment },
748 { "spf_received", vtype_stringptr, &spf_received },
749 { "spf_result", vtype_stringptr, &spf_result },
750 { "spf_result_guessed", vtype_bool, &spf_result_guessed },
751 { "spf_smtp_comment", vtype_stringptr, &spf_smtp_comment },
752 #endif
753 { "spool_directory", vtype_stringptr, &spool_directory },
754 { "spool_inodes", vtype_pinodes, (void *)TRUE },
755 { "spool_space", vtype_pspace, (void *)TRUE },
756 #ifdef EXPERIMENTAL_SRS
757 { "srs_db_address", vtype_stringptr, &srs_db_address },
758 { "srs_db_key", vtype_stringptr, &srs_db_key },
759 { "srs_orig_recipient", vtype_stringptr, &srs_orig_recipient },
760 { "srs_orig_sender", vtype_stringptr, &srs_orig_sender },
761 #endif
762 #if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
763 { "srs_recipient", vtype_stringptr, &srs_recipient },
764 #endif
765 #ifdef EXPERIMENTAL_SRS
766 { "srs_status", vtype_stringptr, &srs_status },
767 #endif
768 { "thisaddress", vtype_stringptr, &filter_thisaddress },
769
770 /* The non-(in,out) variables are now deprecated */
771 { "tls_bits", vtype_int, &tls_in.bits },
772 { "tls_certificate_verified", vtype_int, &tls_in.certificate_verified },
773 { "tls_cipher", vtype_stringptr, &tls_in.cipher },
774
775 { "tls_in_bits", vtype_int, &tls_in.bits },
776 { "tls_in_certificate_verified", vtype_int, &tls_in.certificate_verified },
777 { "tls_in_cipher", vtype_stringptr, &tls_in.cipher },
778 { "tls_in_cipher_std", vtype_stringptr, &tls_in.cipher_stdname },
779 { "tls_in_ocsp", vtype_int, &tls_in.ocsp },
780 { "tls_in_ourcert", vtype_cert, &tls_in.ourcert },
781 { "tls_in_peercert", vtype_cert, &tls_in.peercert },
782 { "tls_in_peerdn", vtype_stringptr, &tls_in.peerdn },
783 #ifdef EXPERIMENTAL_TLS_RESUME
784 { "tls_in_resumption", vtype_int, &tls_in.resumption },
785 #endif
786 #ifndef DISABLE_TLS
787 { "tls_in_sni", vtype_stringptr, &tls_in.sni },
788 #endif
789 { "tls_in_ver", vtype_stringptr, &tls_in.ver },
790 { "tls_out_bits", vtype_int, &tls_out.bits },
791 { "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified },
792 { "tls_out_cipher", vtype_stringptr, &tls_out.cipher },
793 { "tls_out_cipher_std", vtype_stringptr, &tls_out.cipher_stdname },
794 #ifdef SUPPORT_DANE
795 { "tls_out_dane", vtype_bool, &tls_out.dane_verified },
796 #endif
797 { "tls_out_ocsp", vtype_int, &tls_out.ocsp },
798 { "tls_out_ourcert", vtype_cert, &tls_out.ourcert },
799 { "tls_out_peercert", vtype_cert, &tls_out.peercert },
800 { "tls_out_peerdn", vtype_stringptr, &tls_out.peerdn },
801 #ifdef EXPERIMENTAL_TLS_RESUME
802 { "tls_out_resumption", vtype_int, &tls_out.resumption },
803 #endif
804 #ifndef DISABLE_TLS
805 { "tls_out_sni", vtype_stringptr, &tls_out.sni },
806 #endif
807 #ifdef SUPPORT_DANE
808 { "tls_out_tlsa_usage", vtype_int, &tls_out.tlsa_usage },
809 #endif
810 { "tls_out_ver", vtype_stringptr, &tls_out.ver },
811
812 { "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, /* mind the alphabetical order! */
813 #ifndef DISABLE_TLS
814 { "tls_sni", vtype_stringptr, &tls_in.sni }, /* mind the alphabetical order! */
815 #endif
816
817 { "tod_bsdinbox", vtype_todbsdin, NULL },
818 { "tod_epoch", vtype_tode, NULL },
819 { "tod_epoch_l", vtype_todel, NULL },
820 { "tod_full", vtype_todf, NULL },
821 { "tod_log", vtype_todl, NULL },
822 { "tod_logfile", vtype_todlf, NULL },
823 { "tod_zone", vtype_todzone, NULL },
824 { "tod_zulu", vtype_todzulu, NULL },
825 { "transport_name", vtype_stringptr, &transport_name },
826 { "value", vtype_stringptr, &lookup_value },
827 { "verify_mode", vtype_stringptr, &verify_mode },
828 { "version_number", vtype_stringptr, &version_string },
829 { "warn_message_delay", vtype_stringptr, &warnmsg_delay },
830 { "warn_message_recipient",vtype_stringptr, &warnmsg_recipients },
831 { "warn_message_recipients",vtype_stringptr,&warnmsg_recipients },
832 { "warnmsg_delay", vtype_stringptr, &warnmsg_delay },
833 { "warnmsg_recipient", vtype_stringptr, &warnmsg_recipients },
834 { "warnmsg_recipients", vtype_stringptr, &warnmsg_recipients }
835 };
836
837 static int var_table_size = nelem(var_table);
838 static uschar var_buffer[256];
839 static BOOL malformed_header;
840
841 /* For textual hashes */
842
843 static const char *hashcodes = "abcdefghijklmnopqrtsuvwxyz"
844 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
845 "0123456789";
846
847 enum { HMAC_MD5, HMAC_SHA1 };
848
849 /* For numeric hashes */
850
851 static unsigned int prime[] = {
852 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
853 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
854 73, 79, 83, 89, 97, 101, 103, 107, 109, 113};
855
856 /* For printing modes in symbolic form */
857
858 static uschar *mtable_normal[] =
859 { US"---", US"--x", US"-w-", US"-wx", US"r--", US"r-x", US"rw-", US"rwx" };
860
861 static uschar *mtable_setid[] =
862 { US"--S", US"--s", US"-wS", US"-ws", US"r-S", US"r-s", US"rwS", US"rws" };
863
864 static uschar *mtable_sticky[] =
865 { US"--T", US"--t", US"-wT", US"-wt", US"r-T", US"r-t", US"rwT", US"rwt" };
866
867 /* flags for find_header() */
868 #define FH_EXISTS_ONLY BIT(0)
869 #define FH_WANT_RAW BIT(1)
870 #define FH_WANT_LIST BIT(2)
871
872
873 /*************************************************
874 * Tables for UTF-8 support *
875 *************************************************/
876
877 /* Table of the number of extra characters, indexed by the first character
878 masked with 0x3f. The highest number for a valid UTF-8 character is in fact
879 0x3d. */
880
881 static uschar utf8_table1[] = {
882 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
883 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
884 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
885 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
886
887 /* These are the masks for the data bits in the first byte of a character,
888 indexed by the number of additional bytes. */
889
890 static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
891
892 /* Get the next UTF-8 character, advancing the pointer. */
893
894 #define GETUTF8INC(c, ptr) \
895 c = *ptr++; \
896 if ((c & 0xc0) == 0xc0) \
897 { \
898 int a = utf8_table1[c & 0x3f]; /* Number of additional bytes */ \
899 int s = 6*a; \
900 c = (c & utf8_table2[a]) << s; \
901 while (a-- > 0) \
902 { \
903 s -= 6; \
904 c |= (*ptr++ & 0x3f) << s; \
905 } \
906 }
907
908
909
910 static uschar * base32_chars = US"abcdefghijklmnopqrstuvwxyz234567";
911
912 /*************************************************
913 * Binary chop search on a table *
914 *************************************************/
915
916 /* This is used for matching expansion items and operators.
917
918 Arguments:
919 name the name that is being sought
920 table the table to search
921 table_size the number of items in the table
922
923 Returns: the offset in the table, or -1
924 */
925
926 static int
927 chop_match(uschar *name, uschar **table, int table_size)
928 {
929 uschar **bot = table;
930 uschar **top = table + table_size;
931
932 while (top > bot)
933 {
934 uschar **mid = bot + (top - bot)/2;
935 int c = Ustrcmp(name, *mid);
936 if (c == 0) return mid - table;
937 if (c > 0) bot = mid + 1; else top = mid;
938 }
939
940 return -1;
941 }
942
943
944
945 /*************************************************
946 * Check a condition string *
947 *************************************************/
948
949 /* This function is called to expand a string, and test the result for a "true"
950 or "false" value. Failure of the expansion yields FALSE; logged unless it was a
951 forced fail or lookup defer.
952
953 We used to release all store used, but this is not not safe due
954 to ${dlfunc } and ${acl }. In any case expand_string_internal()
955 is reasonably careful to release what it can.
956
957 The actual false-value tests should be replicated for ECOND_BOOL_LAX.
958
959 Arguments:
960 condition the condition string
961 m1 text to be incorporated in panic error
962 m2 ditto
963
964 Returns: TRUE if condition is met, FALSE if not
965 */
966
967 BOOL
968 expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
969 {
970 uschar * ss = expand_string(condition);
971 if (!ss)
972 {
973 if (!f.expand_string_forcedfail && !f.search_find_defer)
974 log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand condition \"%s\" "
975 "for %s %s: %s", condition, m1, m2, expand_string_message);
976 return FALSE;
977 }
978 return *ss && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
979 strcmpic(ss, US"false") != 0;
980 }
981
982
983
984
985 /*************************************************
986 * Pseudo-random number generation *
987 *************************************************/
988
989 /* Pseudo-random number generation. The result is not "expected" to be
990 cryptographically strong but not so weak that someone will shoot themselves
991 in the foot using it as a nonce in some email header scheme or whatever
992 weirdness they'll twist this into. The result should ideally handle fork().
993
994 However, if we're stuck unable to provide this, then we'll fall back to
995 appallingly bad randomness.
996
997 If DISABLE_TLS is not defined then this will not be used except as an emergency
998 fallback.
999
1000 Arguments:
1001 max range maximum
1002 Returns a random number in range [0, max-1]
1003 */
1004
1005 #ifndef DISABLE_TLS
1006 # define vaguely_random_number vaguely_random_number_fallback
1007 #endif
1008 int
1009 vaguely_random_number(int max)
1010 {
1011 #ifndef DISABLE_TLS
1012 # undef vaguely_random_number
1013 #endif
1014 static pid_t pid = 0;
1015 pid_t p2;
1016
1017 if ((p2 = getpid()) != pid)
1018 {
1019 if (pid != 0)
1020 {
1021
1022 #ifdef HAVE_ARC4RANDOM
1023 /* cryptographically strong randomness, common on *BSD platforms, not
1024 so much elsewhere. Alas. */
1025 # ifndef NOT_HAVE_ARC4RANDOM_STIR
1026 arc4random_stir();
1027 # endif
1028 #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
1029 # ifdef HAVE_SRANDOMDEV
1030 /* uses random(4) for seeding */
1031 srandomdev();
1032 # else
1033 {
1034 struct timeval tv;
1035 gettimeofday(&tv, NULL);
1036 srandom(tv.tv_sec | tv.tv_usec | getpid());
1037 }
1038 # endif
1039 #else
1040 /* Poor randomness and no seeding here */
1041 #endif
1042
1043 }
1044 pid = p2;
1045 }
1046
1047 #ifdef HAVE_ARC4RANDOM
1048 return arc4random() % max;
1049 #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
1050 return random() % max;
1051 #else
1052 /* This one returns a 16-bit number, definitely not crypto-strong */
1053 return random_number(max);
1054 #endif
1055 }
1056
1057
1058
1059
1060 /*************************************************
1061 * Pick out a name from a string *
1062 *************************************************/
1063
1064 /* If the name is too long, it is silently truncated.
1065
1066 Arguments:
1067 name points to a buffer into which to put the name
1068 max is the length of the buffer
1069 s points to the first alphabetic character of the name
1070 extras chars other than alphanumerics to permit
1071
1072 Returns: pointer to the first character after the name
1073
1074 Note: The test for *s != 0 in the while loop is necessary because
1075 Ustrchr() yields non-NULL if the character is zero (which is not something
1076 I expected). */
1077
1078 static const uschar *
1079 read_name(uschar *name, int max, const uschar *s, uschar *extras)
1080 {
1081 int ptr = 0;
1082 while (*s && (isalnum(*s) || Ustrchr(extras, *s) != NULL))
1083 {
1084 if (ptr < max-1) name[ptr++] = *s;
1085 s++;
1086 }
1087 name[ptr] = 0;
1088 return s;
1089 }
1090
1091
1092
1093 /*************************************************
1094 * Pick out the rest of a header name *
1095 *************************************************/
1096
1097 /* A variable name starting $header_ (or just $h_ for those who like
1098 abbreviations) might not be the complete header name because headers can
1099 contain any printing characters in their names, except ':'. This function is
1100 called to read the rest of the name, chop h[eader]_ off the front, and put ':'
1101 on the end, if the name was terminated by white space.
1102
1103 Arguments:
1104 name points to a buffer in which the name read so far exists
1105 max is the length of the buffer
1106 s points to the first character after the name so far, i.e. the
1107 first non-alphameric character after $header_xxxxx
1108
1109 Returns: a pointer to the first character after the header name
1110 */
1111
1112 static const uschar *
1113 read_header_name(uschar *name, int max, const uschar *s)
1114 {
1115 int prelen = Ustrchr(name, '_') - name + 1;
1116 int ptr = Ustrlen(name) - prelen;
1117 if (ptr > 0) memmove(name, name+prelen, ptr);
1118 while (mac_isgraph(*s) && *s != ':')
1119 {
1120 if (ptr < max-1) name[ptr++] = *s;
1121 s++;
1122 }
1123 if (*s == ':') s++;
1124 name[ptr++] = ':';
1125 name[ptr] = 0;
1126 return s;
1127 }
1128
1129
1130
1131 /*************************************************
1132 * Pick out a number from a string *
1133 *************************************************/
1134
1135 /* Arguments:
1136 n points to an integer into which to put the number
1137 s points to the first digit of the number
1138
1139 Returns: a pointer to the character after the last digit
1140 */
1141 /*XXX consider expanding to int_eximarith_t. But the test for
1142 "overbig numbers" in 0002 still needs to overflow it. */
1143
1144 static uschar *
1145 read_number(int *n, uschar *s)
1146 {
1147 *n = 0;
1148 while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
1149 return s;
1150 }
1151
1152 static const uschar *
1153 read_cnumber(int *n, const uschar *s)
1154 {
1155 *n = 0;
1156 while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
1157 return s;
1158 }
1159
1160
1161
1162 /*************************************************
1163 * Extract keyed subfield from a string *
1164 *************************************************/
1165
1166 /* The yield is in dynamic store; NULL means that the key was not found.
1167
1168 Arguments:
1169 key points to the name of the key
1170 s points to the string from which to extract the subfield
1171
1172 Returns: NULL if the subfield was not found, or
1173 a pointer to the subfield's data
1174 */
1175
1176 uschar *
1177 expand_getkeyed(const uschar * key, const uschar * s)
1178 {
1179 int length = Ustrlen(key);
1180 Uskip_whitespace(&s);
1181
1182 /* Loop to search for the key */
1183
1184 while (*s)
1185 {
1186 int dkeylength;
1187 uschar * data;
1188 const uschar * dkey = s;
1189
1190 while (*s && *s != '=' && !isspace(*s)) s++;
1191 dkeylength = s - dkey;
1192 if (Uskip_whitespace(&s) == '=') while (isspace(*++s));
1193
1194 data = string_dequote(&s);
1195 if (length == dkeylength && strncmpic(key, dkey, length) == 0)
1196 return data;
1197
1198 Uskip_whitespace(&s);
1199 }
1200
1201 return NULL;
1202 }
1203
1204
1205
1206 static var_entry *
1207 find_var_ent(uschar * name)
1208 {
1209 int first = 0;
1210 int last = var_table_size;
1211
1212 while (last > first)
1213 {
1214 int middle = (first + last)/2;
1215 int c = Ustrcmp(name, var_table[middle].name);
1216
1217 if (c > 0) { first = middle + 1; continue; }
1218 if (c < 0) { last = middle; continue; }
1219 return &var_table[middle];
1220 }
1221 return NULL;
1222 }
1223
1224 /*************************************************
1225 * Extract numbered subfield from string *
1226 *************************************************/
1227
1228 /* Extracts a numbered field from a string that is divided by tokens - for
1229 example a line from /etc/passwd is divided by colon characters. First field is
1230 numbered one. Negative arguments count from the right. Zero returns the whole
1231 string. Returns NULL if there are insufficient tokens in the string
1232
1233 ***WARNING***
1234 Modifies final argument - this is a dynamically generated string, so that's OK.
1235
1236 Arguments:
1237 field number of field to be extracted,
1238 first field = 1, whole string = 0, last field = -1
1239 separators characters that are used to break string into tokens
1240 s points to the string from which to extract the subfield
1241
1242 Returns: NULL if the field was not found,
1243 a pointer to the field's data inside s (modified to add 0)
1244 */
1245
1246 static uschar *
1247 expand_gettokened (int field, uschar *separators, uschar *s)
1248 {
1249 int sep = 1;
1250 int count;
1251 uschar *ss = s;
1252 uschar *fieldtext = NULL;
1253
1254 if (field == 0) return s;
1255
1256 /* Break the line up into fields in place; for field > 0 we stop when we have
1257 done the number of fields we want. For field < 0 we continue till the end of
1258 the string, counting the number of fields. */
1259
1260 count = (field > 0)? field : INT_MAX;
1261
1262 while (count-- > 0)
1263 {
1264 size_t len;
1265
1266 /* Previous field was the last one in the string. For a positive field
1267 number, this means there are not enough fields. For a negative field number,
1268 check that there are enough, and scan back to find the one that is wanted. */
1269
1270 if (sep == 0)
1271 {
1272 if (field > 0 || (-field) > (INT_MAX - count - 1)) return NULL;
1273 if ((-field) == (INT_MAX - count - 1)) return s;
1274 while (field++ < 0)
1275 {
1276 ss--;
1277 while (ss[-1] != 0) ss--;
1278 }
1279 fieldtext = ss;
1280 break;
1281 }
1282
1283 /* Previous field was not last in the string; save its start and put a
1284 zero at its end. */
1285
1286 fieldtext = ss;
1287 len = Ustrcspn(ss, separators);
1288 sep = ss[len];
1289 ss[len] = 0;
1290 ss += len + 1;
1291 }
1292
1293 return fieldtext;
1294 }
1295
1296
1297 static uschar *
1298 expand_getlistele(int field, const uschar * list)
1299 {
1300 const uschar * tlist = list;
1301 int sep = 0;
1302 uschar dummy;
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_catn(g, US";\n\tiprev=temperror", 19);
1713 else if (host_lookup_failed)
1714 g = string_catn(g, US";\n\tiprev=fail", 13);
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 if (len > message_size) len = message_size;
1992 *ss = body = store_malloc(len+1);
1993 body[0] = 0;
1994 if (vp->type == vtype_msgbody_end)
1995 {
1996 struct stat statbuf;
1997 if (fstat(deliver_datafile, &statbuf) == 0)
1998 {
1999 start_offset = statbuf.st_size - len;
2000 if (start_offset < SPOOL_DATA_START_OFFSET)
2001 start_offset = SPOOL_DATA_START_OFFSET;
2002 }
2003 }
2004 if (lseek(deliver_datafile, start_offset, SEEK_SET) < 0)
2005 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "deliver_datafile lseek: %s",
2006 strerror(errno));
2007 len = read(deliver_datafile, body, len);
2008 if (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 return fn();
2071 }
2072
2073 case vtype_pspace:
2074 {
2075 int inodes;
2076 sprintf(CS var_buffer, PR_EXIM_ARITH,
2077 receive_statvfs(val == (void *)TRUE, &inodes));
2078 }
2079 return var_buffer;
2080
2081 case vtype_pinodes:
2082 {
2083 int inodes;
2084 (void) receive_statvfs(val == (void *)TRUE, &inodes);
2085 sprintf(CS var_buffer, "%d", inodes);
2086 }
2087 return var_buffer;
2088
2089 case vtype_cert:
2090 return *(void **)val ? US"<cert>" : US"";
2091
2092 #ifndef DISABLE_DKIM
2093 case vtype_dkim:
2094 return dkim_exim_expand_query((int)(long)val);
2095 #endif
2096
2097 }
2098
2099 return NULL; /* Unknown variable. Silences static checkers. */
2100 }
2101
2102
2103
2104
2105 void
2106 modify_variable(uschar *name, void * value)
2107 {
2108 var_entry * vp;
2109 if ((vp = find_var_ent(name))) vp->value = value;
2110 return; /* Unknown variable name, fail silently */
2111 }
2112
2113
2114
2115
2116
2117
2118 /*************************************************
2119 * Read and expand substrings *
2120 *************************************************/
2121
2122 /* This function is called to read and expand argument substrings for various
2123 expansion items. Some have a minimum requirement that is less than the maximum;
2124 in these cases, the first non-present one is set to NULL.
2125
2126 Arguments:
2127 sub points to vector of pointers to set
2128 n maximum number of substrings
2129 m minimum required
2130 sptr points to current string pointer
2131 skipping the skipping flag
2132 check_end if TRUE, check for final '}'
2133 name name of item, for error message
2134 resetok if not NULL, pointer to flag - write FALSE if unsafe to reset
2135 the store.
2136
2137 Returns: 0 OK; string pointer updated
2138 1 curly bracketing error (too few arguments)
2139 2 too many arguments (only if check_end is set); message set
2140 3 other error (expansion failure)
2141 */
2142
2143 static int
2144 read_subs(uschar **sub, int n, int m, const uschar **sptr, BOOL skipping,
2145 BOOL check_end, uschar *name, BOOL *resetok)
2146 {
2147 const uschar *s = *sptr;
2148
2149 Uskip_whitespace(&s);
2150 for (int i = 0; i < n; i++)
2151 {
2152 if (*s != '{')
2153 {
2154 if (i < m)
2155 {
2156 expand_string_message = string_sprintf("Not enough arguments for '%s' "
2157 "(min is %d)", name, m);
2158 return 1;
2159 }
2160 sub[i] = NULL;
2161 break;
2162 }
2163 if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, resetok)))
2164 return 3;
2165 if (*s++ != '}') return 1;
2166 Uskip_whitespace(&s);
2167 }
2168 if (check_end && *s++ != '}')
2169 {
2170 if (s[-1] == '{')
2171 {
2172 expand_string_message = string_sprintf("Too many arguments for '%s' "
2173 "(max is %d)", name, n);
2174 return 2;
2175 }
2176 expand_string_message = string_sprintf("missing '}' after '%s'", name);
2177 return 1;
2178 }
2179
2180 *sptr = s;
2181 return 0;
2182 }
2183
2184
2185
2186
2187 /*************************************************
2188 * Elaborate message for bad variable *
2189 *************************************************/
2190
2191 /* For the "unknown variable" message, take a look at the variable's name, and
2192 give additional information about possible ACL variables. The extra information
2193 is added on to expand_string_message.
2194
2195 Argument: the name of the variable
2196 Returns: nothing
2197 */
2198
2199 static void
2200 check_variable_error_message(uschar *name)
2201 {
2202 if (Ustrncmp(name, "acl_", 4) == 0)
2203 expand_string_message = string_sprintf("%s (%s)", expand_string_message,
2204 (name[4] == 'c' || name[4] == 'm')?
2205 (isalpha(name[5])?
2206 US"6th character of a user-defined ACL variable must be a digit or underscore" :
2207 US"strict_acl_vars is set" /* Syntax is OK, it has to be this */
2208 ) :
2209 US"user-defined ACL variables must start acl_c or acl_m");
2210 }
2211
2212
2213
2214 /*
2215 Load args from sub array to globals, and call acl_check().
2216 Sub array will be corrupted on return.
2217
2218 Returns: OK access is granted by an ACCEPT verb
2219 DISCARD access is (apparently) granted by a DISCARD verb
2220 FAIL access is denied
2221 FAIL_DROP access is denied; drop the connection
2222 DEFER can't tell at the moment
2223 ERROR disaster
2224 */
2225 static int
2226 eval_acl(uschar ** sub, int nsub, uschar ** user_msgp)
2227 {
2228 int i;
2229 int sav_narg = acl_narg;
2230 int ret;
2231 uschar * dummy_logmsg;
2232 extern int acl_where;
2233
2234 if(--nsub > nelem(acl_arg)) nsub = nelem(acl_arg);
2235 for (i = 0; i < nsub && sub[i+1]; i++)
2236 {
2237 uschar * tmp = acl_arg[i];
2238 acl_arg[i] = sub[i+1]; /* place callers args in the globals */
2239 sub[i+1] = tmp; /* stash the old args using our caller's storage */
2240 }
2241 acl_narg = i;
2242 while (i < nsub)
2243 {
2244 sub[i+1] = acl_arg[i];
2245 acl_arg[i++] = NULL;
2246 }
2247
2248 DEBUG(D_expand)
2249 debug_printf_indent("expanding: acl: %s arg: %s%s\n",
2250 sub[0],
2251 acl_narg>0 ? acl_arg[0] : US"<none>",
2252 acl_narg>1 ? " +more" : "");
2253
2254 ret = acl_eval(acl_where, sub[0], user_msgp, &dummy_logmsg);
2255
2256 for (i = 0; i < nsub; i++)
2257 acl_arg[i] = sub[i+1]; /* restore old args */
2258 acl_narg = sav_narg;
2259
2260 return ret;
2261 }
2262
2263
2264
2265
2266 /* Return pointer to dewrapped string, with enclosing specified chars removed.
2267 The given string is modified on return. Leading whitespace is skipped while
2268 looking for the opening wrap character, then the rest is scanned for the trailing
2269 (non-escaped) wrap character. A backslash in the string will act as an escape.
2270
2271 A nul is written over the trailing wrap, and a pointer to the char after the
2272 leading wrap is returned.
2273
2274 Arguments:
2275 s String for de-wrapping
2276 wrap Two-char string, the first being the opener, second the closer wrapping
2277 character
2278 Return:
2279 Pointer to de-wrapped string, or NULL on error (with expand_string_message set).
2280 */
2281
2282 static uschar *
2283 dewrap(uschar * s, const uschar * wrap)
2284 {
2285 uschar * p = s;
2286 unsigned depth = 0;
2287 BOOL quotesmode = wrap[0] == wrap[1];
2288
2289 if (Uskip_whitespace(&p) == *wrap)
2290 {
2291 s = ++p;
2292 wrap++;
2293 while (*p)
2294 {
2295 if (*p == '\\') p++;
2296 else if (!quotesmode && *p == wrap[-1]) depth++;
2297 else if (*p == *wrap)
2298 if (depth == 0)
2299 {
2300 *p = '\0';
2301 return s;
2302 }
2303 else
2304 depth--;
2305 p++;
2306 }
2307 }
2308 expand_string_message = string_sprintf("missing '%c'", *wrap);
2309 return NULL;
2310 }
2311
2312
2313 /* Pull off the leading array or object element, returning
2314 a copy in an allocated string. Update the list pointer.
2315
2316 The element may itself be an abject or array.
2317 Return NULL when the list is empty.
2318 */
2319
2320 static uschar *
2321 json_nextinlist(const uschar ** list)
2322 {
2323 unsigned array_depth = 0, object_depth = 0;
2324 const uschar * s = *list, * item;
2325
2326 skip_whitespace(&s);
2327
2328 for (item = s;
2329 *s && (*s != ',' || array_depth != 0 || object_depth != 0);
2330 s++)
2331 switch (*s)
2332 {
2333 case '[': array_depth++; break;
2334 case ']': array_depth--; break;
2335 case '{': object_depth++; break;
2336 case '}': object_depth--; break;
2337 }
2338 *list = *s ? s+1 : s;
2339 if (item == s) return NULL;
2340 item = string_copyn(item, s - item);
2341 DEBUG(D_expand) debug_printf_indent(" json ele: '%s'\n", item);
2342 return US item;
2343 }
2344
2345
2346
2347 /************************************************/
2348 /* Return offset in ops table, or -1 if not found.
2349 Repoint to just after the operator in the string.
2350
2351 Argument:
2352 ss string representation of operator
2353 opname split-out operator name
2354 */
2355
2356 static int
2357 identify_operator(const uschar ** ss, uschar ** opname)
2358 {
2359 const uschar * s = *ss;
2360 uschar name[256];
2361
2362 /* Numeric comparisons are symbolic */
2363
2364 if (*s == '=' || *s == '>' || *s == '<')
2365 {
2366 int p = 0;
2367 name[p++] = *s++;
2368 if (*s == '=')
2369 {
2370 name[p++] = '=';
2371 s++;
2372 }
2373 name[p] = 0;
2374 }
2375
2376 /* All other conditions are named */
2377
2378 else
2379 s = read_name(name, sizeof(name), s, US"_");
2380 *ss = s;
2381
2382 /* If we haven't read a name, it means some non-alpha character is first. */
2383
2384 if (!name[0])
2385 {
2386 expand_string_message = string_sprintf("condition name expected, "
2387 "but found \"%.16s\"", s);
2388 return -1;
2389 }
2390 if (opname)
2391 *opname = string_copy(name);
2392
2393 return chop_match(name, cond_table, nelem(cond_table));
2394 }
2395
2396
2397 /*************************************************
2398 * Handle MD5 or SHA-1 computation for HMAC *
2399 *************************************************/
2400
2401 /* These are some wrapping functions that enable the HMAC code to be a bit
2402 cleaner. A good compiler will spot the tail recursion.
2403
2404 Arguments:
2405 type HMAC_MD5 or HMAC_SHA1
2406 remaining are as for the cryptographic hash functions
2407
2408 Returns: nothing
2409 */
2410
2411 static void
2412 chash_start(int type, void * base)
2413 {
2414 if (type == HMAC_MD5)
2415 md5_start((md5 *)base);
2416 else
2417 sha1_start((hctx *)base);
2418 }
2419
2420 static void
2421 chash_mid(int type, void * base, const uschar * string)
2422 {
2423 if (type == HMAC_MD5)
2424 md5_mid((md5 *)base, string);
2425 else
2426 sha1_mid((hctx *)base, string);
2427 }
2428
2429 static void
2430 chash_end(int type, void * base, const uschar * string, int length,
2431 uschar * digest)
2432 {
2433 if (type == HMAC_MD5)
2434 md5_end((md5 *)base, string, length, digest);
2435 else
2436 sha1_end((hctx *)base, string, length, digest);
2437 }
2438
2439
2440
2441
2442 #ifdef EXPERIMENTAL_SRS_NATIVE
2443 /* Do an hmac_md5. The result is _not_ nul-terminated, and is sized as
2444 the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
2445
2446 Arguments:
2447 key encoding key, nul-terminated
2448 src data to be hashed, nul-terminated
2449 buf output buffer
2450 len size of output buffer
2451 */
2452
2453 static void
2454 hmac_md5(const uschar * key, const uschar * src, uschar * buf, unsigned len)
2455 {
2456 md5 md5_base;
2457 const uschar * keyptr;
2458 uschar * p;
2459 unsigned int keylen;
2460
2461 #define MD5_HASHLEN 16
2462 #define MD5_HASHBLOCKLEN 64
2463
2464 uschar keyhash[MD5_HASHLEN];
2465 uschar innerhash[MD5_HASHLEN];
2466 uschar finalhash[MD5_HASHLEN];
2467 uschar innerkey[MD5_HASHBLOCKLEN];
2468 uschar outerkey[MD5_HASHBLOCKLEN];
2469
2470 keyptr = key;
2471 keylen = Ustrlen(keyptr);
2472
2473 /* If the key is longer than the hash block length, then hash the key
2474 first */
2475
2476 if (keylen > MD5_HASHBLOCKLEN)
2477 {
2478 chash_start(HMAC_MD5, &md5_base);
2479 chash_end(HMAC_MD5, &md5_base, keyptr, keylen, keyhash);
2480 keyptr = keyhash;
2481 keylen = MD5_HASHLEN;
2482 }
2483
2484 /* Now make the inner and outer key values */
2485
2486 memset(innerkey, 0x36, MD5_HASHBLOCKLEN);
2487 memset(outerkey, 0x5c, MD5_HASHBLOCKLEN);
2488
2489 for (int i = 0; i < keylen; i++)
2490 {
2491 innerkey[i] ^= keyptr[i];
2492 outerkey[i] ^= keyptr[i];
2493 }
2494
2495 /* Now do the hashes */
2496
2497 chash_start(HMAC_MD5, &md5_base);
2498 chash_mid(HMAC_MD5, &md5_base, innerkey);
2499 chash_end(HMAC_MD5, &md5_base, src, Ustrlen(src), innerhash);
2500
2501 chash_start(HMAC_MD5, &md5_base);
2502 chash_mid(HMAC_MD5, &md5_base, outerkey);
2503 chash_end(HMAC_MD5, &md5_base, innerhash, MD5_HASHLEN, finalhash);
2504
2505 /* Encode the final hash as a hex string, limited by output buffer size */
2506
2507 p = buf;
2508 for (int i = 0, j = len; i < MD5_HASHLEN; i++)
2509 {
2510 if (j-- <= 0) break;
2511 *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
2512 if (j-- <= 0) break;
2513 *p++ = hex_digits[finalhash[i] & 0x0f];
2514 }
2515 return;
2516 }
2517 #endif /*EXPERIMENTAL_SRS_NATIVE*/
2518
2519
2520 /*************************************************
2521 * Read and evaluate a condition *
2522 *************************************************/
2523
2524 /*
2525 Arguments:
2526 s points to the start of the condition text
2527 resetok points to a BOOL which is written false if it is unsafe to
2528 free memory. Certain condition types (acl) may have side-effect
2529 allocation which must be preserved.
2530 yield points to a BOOL to hold the result of the condition test;
2531 if NULL, we are just reading through a condition that is
2532 part of an "or" combination to check syntax, or in a state
2533 where the answer isn't required
2534
2535 Returns: a pointer to the first character after the condition, or
2536 NULL after an error
2537 */
2538
2539 static const uschar *
2540 eval_condition(const uschar *s, BOOL *resetok, BOOL *yield)
2541 {
2542 BOOL testfor = TRUE;
2543 BOOL tempcond, combined_cond;
2544 BOOL *subcondptr;
2545 BOOL sub2_honour_dollar = TRUE;
2546 BOOL is_forany, is_json, is_jsons;
2547 int rc, cond_type, roffset;
2548 int_eximarith_t num[2];
2549 struct stat statbuf;
2550 uschar * opname;
2551 uschar name[256];
2552 const uschar *sub[10];
2553
2554 const pcre *re;
2555 const uschar *rerror;
2556
2557 for (;;)
2558 if (Uskip_whitespace(&s) == '!') { testfor = !testfor; s++; } else break;
2559
2560 switch(cond_type = identify_operator(&s, &opname))
2561 {
2562 /* def: tests for a non-empty variable, or for the existence of a header. If
2563 yield == NULL we are in a skipping state, and don't care about the answer. */
2564
2565 case ECOND_DEF:
2566 {
2567 uschar * t;
2568
2569 if (*s != ':')
2570 {
2571 expand_string_message = US"\":\" expected after \"def\"";
2572 return NULL;
2573 }
2574
2575 s = read_name(name, sizeof(name), s+1, US"_");
2576
2577 /* Test for a header's existence. If the name contains a closing brace
2578 character, this may be a user error where the terminating colon has been
2579 omitted. Set a flag to adjust a subsequent error message in this case. */
2580
2581 if ( ( *(t = name) == 'h'
2582 || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
2583 )
2584 && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
2585 )
2586 {
2587 s = read_header_name(name, sizeof(name), s);
2588 /* {-for-text-editors */
2589 if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
2590 if (yield) *yield =
2591 (find_header(name, NULL, FH_EXISTS_ONLY, NULL) != NULL) == testfor;
2592 }
2593
2594 /* Test for a variable's having a non-empty value. A non-existent variable
2595 causes an expansion failure. */
2596
2597 else
2598 {
2599 if (!(t = find_variable(name, TRUE, yield == NULL, NULL)))
2600 {
2601 expand_string_message = name[0]
2602 ? string_sprintf("unknown variable \"%s\" after \"def:\"", name)
2603 : US"variable name omitted after \"def:\"";
2604 check_variable_error_message(name);
2605 return NULL;
2606 }
2607 if (yield) *yield = (t[0] != 0) == testfor;
2608 }
2609
2610 return s;
2611 }
2612
2613
2614 /* first_delivery tests for first delivery attempt */
2615
2616 case ECOND_FIRST_DELIVERY:
2617 if (yield) *yield = f.deliver_firsttime == testfor;
2618 return s;
2619
2620
2621 /* queue_running tests for any process started by a queue runner */
2622
2623 case ECOND_QUEUE_RUNNING:
2624 if (yield) *yield = (queue_run_pid != (pid_t)0) == testfor;
2625 return s;
2626
2627
2628 /* exists: tests for file existence
2629 isip: tests for any IP address
2630 isip4: tests for an IPv4 address
2631 isip6: tests for an IPv6 address
2632 pam: does PAM authentication
2633 radius: does RADIUS authentication
2634 ldapauth: does LDAP authentication
2635 pwcheck: does Cyrus SASL pwcheck authentication
2636 */
2637
2638 case ECOND_EXISTS:
2639 case ECOND_ISIP:
2640 case ECOND_ISIP4:
2641 case ECOND_ISIP6:
2642 case ECOND_PAM:
2643 case ECOND_RADIUS:
2644 case ECOND_LDAPAUTH:
2645 case ECOND_PWCHECK:
2646
2647 if (Uskip_whitespace(&s) != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2648
2649 sub[0] = expand_string_internal(s+1, TRUE, &s, yield == NULL, TRUE, resetok);
2650 if (!sub[0]) return NULL;
2651 /* {-for-text-editors */
2652 if (*s++ != '}') goto COND_FAILED_CURLY_END;
2653
2654 if (!yield) return s; /* No need to run the test if skipping */
2655
2656 switch(cond_type)
2657 {
2658 case ECOND_EXISTS:
2659 if ((expand_forbid & RDO_EXISTS) != 0)
2660 {
2661 expand_string_message = US"File existence tests are not permitted";
2662 return NULL;
2663 }
2664 *yield = (Ustat(sub[0], &statbuf) == 0) == testfor;
2665 break;
2666
2667 case ECOND_ISIP:
2668 case ECOND_ISIP4:
2669 case ECOND_ISIP6:
2670 rc = string_is_ip_address(sub[0], NULL);
2671 *yield = ((cond_type == ECOND_ISIP)? (rc != 0) :
2672 (cond_type == ECOND_ISIP4)? (rc == 4) : (rc == 6)) == testfor;
2673 break;
2674
2675 /* Various authentication tests - all optionally compiled */
2676
2677 case ECOND_PAM:
2678 #ifdef SUPPORT_PAM
2679 rc = auth_call_pam(sub[0], &expand_string_message);
2680 goto END_AUTH;
2681 #else
2682 goto COND_FAILED_NOT_COMPILED;
2683 #endif /* SUPPORT_PAM */
2684
2685 case ECOND_RADIUS:
2686 #ifdef RADIUS_CONFIG_FILE
2687 rc = auth_call_radius(sub[0], &expand_string_message);
2688 goto END_AUTH;
2689 #else
2690 goto COND_FAILED_NOT_COMPILED;
2691 #endif /* RADIUS_CONFIG_FILE */
2692
2693 case ECOND_LDAPAUTH:
2694 #ifdef LOOKUP_LDAP
2695 {
2696 /* Just to keep the interface the same */
2697 BOOL do_cache;
2698 int old_pool = store_pool;
2699 store_pool = POOL_SEARCH;
2700 rc = eldapauth_find((void *)(-1), NULL, sub[0], Ustrlen(sub[0]), NULL,
2701 &expand_string_message, &do_cache);
2702 store_pool = old_pool;
2703 }
2704 goto END_AUTH;
2705 #else
2706 goto COND_FAILED_NOT_COMPILED;
2707 #endif /* LOOKUP_LDAP */
2708
2709 case ECOND_PWCHECK:
2710 #ifdef CYRUS_PWCHECK_SOCKET
2711 rc = auth_call_pwcheck(sub[0], &expand_string_message);
2712 goto END_AUTH;
2713 #else
2714 goto COND_FAILED_NOT_COMPILED;
2715 #endif /* CYRUS_PWCHECK_SOCKET */
2716
2717 #if defined(SUPPORT_PAM) || defined(RADIUS_CONFIG_FILE) || \
2718 defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET)
2719 END_AUTH:
2720 if (rc == ERROR || rc == DEFER) return NULL;
2721 *yield = (rc == OK) == testfor;
2722 #endif
2723 }
2724 return s;
2725
2726
2727 /* call ACL (in a conditional context). Accept true, deny false.
2728 Defer is a forced-fail. Anything set by message= goes to $value.
2729 Up to ten parameters are used; we use the braces round the name+args
2730 like the saslauthd condition does, to permit a variable number of args.
2731 See also the expansion-item version EITEM_ACL and the traditional
2732 acl modifier ACLC_ACL.
2733 Since the ACL may allocate new global variables, tell our caller to not
2734 reclaim memory.
2735 */
2736
2737 case ECOND_ACL:
2738 /* ${if acl {{name}{arg1}{arg2}...} {yes}{no}} */
2739 {
2740 uschar *sub[10];
2741 uschar *user_msg;
2742 BOOL cond = FALSE;
2743
2744 Uskip_whitespace(&s);
2745 if (*s++ != '{') goto COND_FAILED_CURLY_START; /*}*/
2746
2747 switch(read_subs(sub, nelem(sub), 1,
2748 &s, yield == NULL, TRUE, name, resetok))
2749 {
2750 case 1: expand_string_message = US"too few arguments or bracketing "
2751 "error for acl";
2752 case 2:
2753 case 3: return NULL;
2754 }
2755
2756 if (yield)
2757 {
2758 int rc;
2759 *resetok = FALSE; /* eval_acl() might allocate; do not reclaim */
2760 switch(rc = eval_acl(sub, nelem(sub), &user_msg))
2761 {
2762 case OK:
2763 cond = TRUE;
2764 case FAIL:
2765 lookup_value = NULL;
2766 if (user_msg)
2767 lookup_value = string_copy(user_msg);
2768 *yield = cond == testfor;
2769 break;
2770
2771 case DEFER:
2772 f.expand_string_forcedfail = TRUE;
2773 /*FALLTHROUGH*/
2774 default:
2775 expand_string_message = string_sprintf("%s from acl \"%s\"",
2776 rc_names[rc], sub[0]);
2777 return NULL;
2778 }
2779 }
2780 return s;
2781 }
2782
2783
2784 /* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
2785
2786 ${if saslauthd {{username}{password}{service}{realm}} {yes}{no}}
2787
2788 However, the last two are optional. That is why the whole set is enclosed
2789 in their own set of braces. */
2790
2791 case ECOND_SASLAUTHD:
2792 #ifndef CYRUS_SASLAUTHD_SOCKET
2793 goto COND_FAILED_NOT_COMPILED;
2794 #else
2795 {
2796 uschar *sub[4];
2797 Uskip_whitespace(&s);
2798 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2799 switch(read_subs(sub, nelem(sub), 2, &s, yield == NULL, TRUE, name,
2800 resetok))
2801 {
2802 case 1: expand_string_message = US"too few arguments or bracketing "
2803 "error for saslauthd";
2804 case 2:
2805 case 3: return NULL;
2806 }
2807 if (!sub[2]) sub[3] = NULL; /* realm if no service */
2808 if (yield)
2809 {
2810 int rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
2811 &expand_string_message);
2812 if (rc == ERROR || rc == DEFER) return NULL;
2813 *yield = (rc == OK) == testfor;
2814 }
2815 return s;
2816 }
2817 #endif /* CYRUS_SASLAUTHD_SOCKET */
2818
2819
2820 /* symbolic operators for numeric and string comparison, and a number of
2821 other operators, all requiring two arguments.
2822
2823 crypteq: encrypts plaintext and compares against an encrypted text,
2824 using crypt(), crypt16(), MD5 or SHA-1
2825 inlist/inlisti: checks if first argument is in the list of the second
2826 match: does a regular expression match and sets up the numerical
2827 variables if it succeeds
2828 match_address: matches in an address list
2829 match_domain: matches in a domain list
2830 match_ip: matches a host list that is restricted to IP addresses
2831 match_local_part: matches in a local part list
2832 */
2833
2834 case ECOND_MATCH_ADDRESS:
2835 case ECOND_MATCH_DOMAIN:
2836 case ECOND_MATCH_IP:
2837 case ECOND_MATCH_LOCAL_PART:
2838 #ifndef EXPAND_LISTMATCH_RHS
2839 sub2_honour_dollar = FALSE;
2840 #endif
2841 /* FALLTHROUGH */
2842
2843 case ECOND_CRYPTEQ:
2844 case ECOND_INLIST:
2845 case ECOND_INLISTI:
2846 case ECOND_MATCH:
2847
2848 case ECOND_NUM_L: /* Numerical comparisons */
2849 case ECOND_NUM_LE:
2850 case ECOND_NUM_E:
2851 case ECOND_NUM_EE:
2852 case ECOND_NUM_G:
2853 case ECOND_NUM_GE:
2854
2855 case ECOND_STR_LT: /* String comparisons */
2856 case ECOND_STR_LTI:
2857 case ECOND_STR_LE:
2858 case ECOND_STR_LEI:
2859 case ECOND_STR_EQ:
2860 case ECOND_STR_EQI:
2861 case ECOND_STR_GT:
2862 case ECOND_STR_GTI:
2863 case ECOND_STR_GE:
2864 case ECOND_STR_GEI:
2865
2866 for (int i = 0; i < 2; i++)
2867 {
2868 /* Sometimes, we don't expand substrings; too many insecure configurations
2869 created using match_address{}{} and friends, where the second param
2870 includes information from untrustworthy sources. */
2871 BOOL honour_dollar = TRUE;
2872 if ((i > 0) && !sub2_honour_dollar)
2873 honour_dollar = FALSE;
2874
2875 if (Uskip_whitespace(&s) != '{')
2876 {
2877 if (i == 0) goto COND_FAILED_CURLY_START;
2878 expand_string_message = string_sprintf("missing 2nd string in {} "
2879 "after \"%s\"", opname);
2880 return NULL;
2881 }
2882 if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL,
2883 honour_dollar, resetok)))
2884 return NULL;
2885 DEBUG(D_expand) if (i == 1 && !sub2_honour_dollar && Ustrchr(sub[1], '$'))
2886 debug_printf_indent("WARNING: the second arg is NOT expanded,"
2887 " for security reasons\n");
2888 if (*s++ != '}') goto COND_FAILED_CURLY_END;
2889
2890 /* Convert to numerical if required; we know that the names of all the
2891 conditions that compare numbers do not start with a letter. This just saves
2892 checking for them individually. */
2893
2894 if (!isalpha(opname[0]) && yield)
2895 if (sub[i][0] == 0)
2896 {
2897 num[i] = 0;
2898 DEBUG(D_expand)
2899 debug_printf_indent("empty string cast to zero for numerical comparison\n");
2900 }
2901 else
2902 {
2903 num[i] = expanded_string_integer(sub[i], FALSE);
2904 if (expand_string_message) return NULL;
2905 }
2906 }
2907
2908 /* Result not required */
2909
2910 if (!yield) return s;
2911
2912 /* Do an appropriate comparison */
2913
2914 switch(cond_type)
2915 {
2916 case ECOND_NUM_E:
2917 case ECOND_NUM_EE:
2918 tempcond = (num[0] == num[1]);
2919 break;
2920
2921 case ECOND_NUM_G:
2922 tempcond = (num[0] > num[1]);
2923 break;
2924
2925 case ECOND_NUM_GE:
2926 tempcond = (num[0] >= num[1]);
2927 break;
2928
2929 case ECOND_NUM_L:
2930 tempcond = (num[0] < num[1]);
2931 break;
2932
2933 case ECOND_NUM_LE:
2934 tempcond = (num[0] <= num[1]);
2935 break;
2936
2937 case ECOND_STR_LT:
2938 tempcond = (Ustrcmp(sub[0], sub[1]) < 0);
2939 break;
2940
2941 case ECOND_STR_LTI:
2942 tempcond = (strcmpic(sub[0], sub[1]) < 0);
2943 break;
2944
2945 case ECOND_STR_LE:
2946 tempcond = (Ustrcmp(sub[0], sub[1]) <= 0);
2947 break;
2948
2949 case ECOND_STR_LEI:
2950 tempcond = (strcmpic(sub[0], sub[1]) <= 0);
2951 break;
2952
2953 case ECOND_STR_EQ:
2954 tempcond = (Ustrcmp(sub[0], sub[1]) == 0);
2955 break;
2956
2957 case ECOND_STR_EQI:
2958 tempcond = (strcmpic(sub[0], sub[1]) == 0);
2959 break;
2960
2961 case ECOND_STR_GT:
2962 tempcond = (Ustrcmp(sub[0], sub[1]) > 0);
2963 break;
2964
2965 case ECOND_STR_GTI:
2966 tempcond = (strcmpic(sub[0], sub[1]) > 0);
2967 break;
2968
2969 case ECOND_STR_GE:
2970 tempcond = (Ustrcmp(sub[0], sub[1]) >= 0);
2971 break;
2972
2973 case ECOND_STR_GEI:
2974 tempcond = (strcmpic(sub[0], sub[1]) >= 0);
2975 break;
2976
2977 case ECOND_MATCH: /* Regular expression match */
2978 if (!(re = pcre_compile(CS sub[1], PCRE_COPT, CCSS &rerror,
2979 &roffset, NULL)))
2980 {
2981 expand_string_message = string_sprintf("regular expression error in "
2982 "\"%s\": %s at offset %d", sub[1], rerror, roffset);
2983 return NULL;
2984 }
2985 tempcond = regex_match_and_setup(re, sub[0], 0, -1);
2986 break;
2987
2988 case ECOND_MATCH_ADDRESS: /* Match in an address list */
2989 rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0, NULL);
2990 goto MATCHED_SOMETHING;
2991
2992 case ECOND_MATCH_DOMAIN: /* Match in a domain list */
2993 rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
2994 MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
2995 goto MATCHED_SOMETHING;
2996
2997 case ECOND_MATCH_IP: /* Match IP address in a host list */
2998 if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) == 0)
2999 {
3000 expand_string_message = string_sprintf("\"%s\" is not an IP address",
3001 sub[0]);
3002 return NULL;
3003 }
3004 else
3005 {
3006 unsigned int *nullcache = NULL;
3007 check_host_block cb;
3008
3009 cb.host_name = US"";
3010 cb.host_address = sub[0];
3011
3012 /* If the host address starts off ::ffff: it is an IPv6 address in
3013 IPv4-compatible mode. Find the IPv4 part for checking against IPv4
3014 addresses. */
3015
3016 cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
3017 cb.host_address + 7 : cb.host_address;
3018
3019 rc = match_check_list(
3020 &sub[1], /* the list */
3021 0, /* separator character */
3022 &hostlist_anchor, /* anchor pointer */
3023 &nullcache, /* cache pointer */
3024 check_host, /* function for testing */
3025 &cb, /* argument for function */
3026 MCL_HOST, /* type of check */
3027 sub[0], /* text for debugging */
3028 NULL); /* where to pass back data */
3029 }
3030 goto MATCHED_SOMETHING;
3031
3032 case ECOND_MATCH_LOCAL_PART:
3033 rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
3034 MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
3035 /* Fall through */
3036 /* VVVVVVVVVVVV */
3037 MATCHED_SOMETHING:
3038 switch(rc)
3039 {
3040 case OK:
3041 tempcond = TRUE;
3042 break;
3043
3044 case FAIL:
3045 tempcond = FALSE;
3046 break;
3047
3048 case DEFER:
3049 expand_string_message = string_sprintf("unable to complete match "
3050 "against \"%s\": %s", sub[1], search_error_message);
3051 return NULL;
3052 }
3053
3054 break;
3055
3056 /* Various "encrypted" comparisons. If the second string starts with
3057 "{" then an encryption type is given. Default to crypt() or crypt16()
3058 (build-time choice). */
3059 /* }-for-text-editors */
3060
3061 case ECOND_CRYPTEQ:
3062 #ifndef SUPPORT_CRYPTEQ
3063 goto COND_FAILED_NOT_COMPILED;
3064 #else
3065 if (strncmpic(sub[1], US"{md5}", 5) == 0)
3066 {
3067 int sublen = Ustrlen(sub[1]+5);
3068 md5 base;
3069 uschar digest[16];
3070
3071 md5_start(&base);
3072 md5_end(&base, sub[0], Ustrlen(sub[0]), digest);
3073
3074 /* If the length that we are comparing against is 24, the MD5 digest
3075 is expressed as a base64 string. This is the way LDAP does it. However,
3076 some other software uses a straightforward hex representation. We assume
3077 this if the length is 32. Other lengths fail. */
3078
3079 if (sublen == 24)
3080 {
3081 uschar *coded = b64encode(CUS digest, 16);
3082 DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
3083 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
3084 tempcond = (Ustrcmp(coded, sub[1]+5) == 0);
3085 }
3086 else if (sublen == 32)
3087 {
3088 uschar coded[36];
3089 for (int i = 0; i < 16; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3090 coded[32] = 0;
3091 DEBUG(D_auth) debug_printf("crypteq: using MD5+hex hashing\n"
3092 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
3093 tempcond = (strcmpic(coded, sub[1]+5) == 0);
3094 }
3095 else
3096 {
3097 DEBUG(D_auth) debug_printf("crypteq: length for MD5 not 24 or 32: "
3098 "fail\n crypted=%s\n", sub[1]+5);
3099 tempcond = FALSE;
3100 }
3101 }
3102
3103 else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
3104 {
3105 int sublen = Ustrlen(sub[1]+6);
3106 hctx h;
3107 uschar digest[20];
3108
3109 sha1_start(&h);
3110 sha1_end(&h, sub[0], Ustrlen(sub[0]), digest);
3111
3112 /* If the length that we are comparing against is 28, assume the SHA1
3113 digest is expressed as a base64 string. If the length is 40, assume a
3114 straightforward hex representation. Other lengths fail. */
3115
3116 if (sublen == 28)
3117 {
3118 uschar *coded = b64encode(CUS digest, 20);
3119 DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
3120 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
3121 tempcond = (Ustrcmp(coded, sub[1]+6) == 0);
3122 }
3123 else if (sublen == 40)
3124 {
3125 uschar coded[44];
3126 for (int i = 0; i < 20; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3127 coded[40] = 0;
3128 DEBUG(D_auth) debug_printf("crypteq: using SHA1+hex hashing\n"
3129 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
3130 tempcond = (strcmpic(coded, sub[1]+6) == 0);
3131 }
3132 else
3133 {
3134 DEBUG(D_auth) debug_printf("crypteq: length for SHA-1 not 28 or 40: "
3135 "fail\n crypted=%s\n", sub[1]+6);
3136 tempcond = FALSE;
3137 }
3138 }
3139
3140 else /* {crypt} or {crypt16} and non-{ at start */
3141 /* }-for-text-editors */
3142 {
3143 int which = 0;
3144 uschar *coded;
3145
3146 if (strncmpic(sub[1], US"{crypt}", 7) == 0)
3147 {
3148 sub[1] += 7;
3149 which = 1;
3150 }
3151 else if (strncmpic(sub[1], US"{crypt16}", 9) == 0)
3152 {
3153 sub[1] += 9;
3154 which = 2;
3155 }
3156 else if (sub[1][0] == '{') /* }-for-text-editors */
3157 {
3158 expand_string_message = string_sprintf("unknown encryption mechanism "
3159 "in \"%s\"", sub[1]);
3160 return NULL;
3161 }
3162
3163 switch(which)
3164 {
3165 case 0: coded = US DEFAULT_CRYPT(CS sub[0], CS sub[1]); break;
3166 case 1: coded = US crypt(CS sub[0], CS sub[1]); break;
3167 default: coded = US crypt16(CS sub[0], CS sub[1]); break;
3168 }
3169
3170 #define STR(s) # s
3171 #define XSTR(s) STR(s)
3172 DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
3173 " subject=%s\n crypted=%s\n",
3174 which == 0 ? XSTR(DEFAULT_CRYPT) : which == 1 ? "crypt" : "crypt16",
3175 coded, sub[1]);
3176 #undef STR
3177 #undef XSTR
3178
3179 /* If the encrypted string contains fewer than two characters (for the
3180 salt), force failure. Otherwise we get false positives: with an empty
3181 string the yield of crypt() is an empty string! */
3182
3183 if (coded)
3184 tempcond = Ustrlen(sub[1]) < 2 ? FALSE : Ustrcmp(coded, sub[1]) == 0;
3185 else if (errno == EINVAL)
3186 tempcond = FALSE;
3187 else
3188 {
3189 expand_string_message = string_sprintf("crypt error: %s\n",
3190 US strerror(errno));
3191 return NULL;
3192 }
3193 }
3194 break;
3195 #endif /* SUPPORT_CRYPTEQ */
3196
3197 case ECOND_INLIST:
3198 case ECOND_INLISTI:
3199 {
3200 const uschar * list = sub[1];
3201 int sep = 0;
3202 uschar *save_iterate_item = iterate_item;
3203 int (*compare)(const uschar *, const uschar *);
3204
3205 DEBUG(D_expand) debug_printf_indent("condition: %s item: %s\n", opname, sub[0]);
3206
3207 tempcond = FALSE;
3208 compare = cond_type == ECOND_INLISTI
3209 ? strcmpic : (int (*)(const uschar *, const uschar *)) strcmp;
3210
3211 while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
3212 {
3213 DEBUG(D_expand) debug_printf_indent(" compare %s\n", iterate_item);
3214 if (compare(sub[0], iterate_item) == 0)
3215 {
3216 tempcond = TRUE;
3217 break;
3218 }
3219 }
3220 iterate_item = save_iterate_item;
3221 }
3222
3223 } /* Switch for comparison conditions */
3224
3225 *yield = tempcond == testfor;
3226 return s; /* End of comparison conditions */
3227
3228
3229 /* and/or: computes logical and/or of several conditions */
3230
3231 case ECOND_AND:
3232 case ECOND_OR:
3233 subcondptr = (yield == NULL) ? NULL : &tempcond;
3234 combined_cond = (cond_type == ECOND_AND);
3235
3236 Uskip_whitespace(&s);
3237 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3238
3239 for (;;)
3240 {
3241 /* {-for-text-editors */
3242 if (Uskip_whitespace(&s) == '}') break;
3243 if (*s != '{') /* }-for-text-editors */
3244 {
3245 expand_string_message = string_sprintf("each subcondition "
3246 "inside an \"%s{...}\" condition must be in its own {}", opname);
3247 return NULL;
3248 }
3249
3250 if (!(s = eval_condition(s+1, resetok, subcondptr)))
3251 {
3252 expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
3253 expand_string_message, opname);
3254 return NULL;
3255 }
3256 Uskip_whitespace(&s);
3257
3258 /* {-for-text-editors */
3259 if (*s++ != '}')
3260 {
3261 /* {-for-text-editors */
3262 expand_string_message = string_sprintf("missing } at end of condition "
3263 "inside \"%s\" group", opname);
3264 return NULL;
3265 }
3266
3267 if (yield)
3268 if (cond_type == ECOND_AND)
3269 {
3270 combined_cond &= tempcond;
3271 if (!combined_cond) subcondptr = NULL; /* once false, don't */
3272 } /* evaluate any more */
3273 else
3274 {
3275 combined_cond |= tempcond;
3276 if (combined_cond) subcondptr = NULL; /* once true, don't */
3277 } /* evaluate any more */
3278 }
3279
3280 if (yield) *yield = (combined_cond == testfor);
3281 return ++s;
3282
3283
3284 /* forall/forany: iterates a condition with different values */
3285
3286 case ECOND_FORALL: is_forany = FALSE; is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3287 case ECOND_FORANY: is_forany = TRUE; is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3288 case ECOND_FORALL_JSON: is_forany = FALSE; is_json = TRUE; is_jsons = FALSE; goto FORMANY;
3289 case ECOND_FORANY_JSON: is_forany = TRUE; is_json = TRUE; is_jsons = FALSE; goto FORMANY;
3290 case ECOND_FORALL_JSONS: is_forany = FALSE; is_json = TRUE; is_jsons = TRUE; goto FORMANY;
3291 case ECOND_FORANY_JSONS: is_forany = TRUE; is_json = TRUE; is_jsons = TRUE; goto FORMANY;
3292
3293 FORMANY:
3294 {
3295 const uschar * list;
3296 int sep = 0;
3297 uschar *save_iterate_item = iterate_item;
3298
3299 DEBUG(D_expand) debug_printf_indent("condition: %s\n", opname);
3300
3301 Uskip_whitespace(&s);
3302 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3303 if (!(sub[0] = expand_string_internal(s, TRUE, &s, yield == NULL, TRUE, resetok)))
3304 return NULL;
3305 /* {-for-text-editors */
3306 if (*s++ != '}') goto COND_FAILED_CURLY_END;
3307
3308 Uskip_whitespace(&s);
3309 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3310
3311 sub[1] = s;
3312
3313 /* Call eval_condition once, with result discarded (as if scanning a
3314 "false" part). This allows us to find the end of the condition, because if
3315 the list it empty, we won't actually evaluate the condition for real. */
3316
3317 if (!(s = eval_condition(sub[1], resetok, NULL)))
3318 {
3319 expand_string_message = string_sprintf("%s inside \"%s\" condition",
3320 expand_string_message, opname);
3321 return NULL;
3322 }
3323 Uskip_whitespace(&s);
3324
3325 /* {-for-text-editors */
3326 if (*s++ != '}')
3327 {
3328 /* {-for-text-editors */
3329 expand_string_message = string_sprintf("missing } at end of condition "
3330 "inside \"%s\"", opname);
3331 return NULL;
3332 }
3333
3334 if (yield) *yield = !testfor;
3335 list = sub[0];
3336 if (is_json) list = dewrap(string_copy(list), US"[]");
3337 while ((iterate_item = is_json
3338 ? json_nextinlist(&list) : string_nextinlist(&list, &sep, NULL, 0)))
3339 {
3340 if (is_jsons)
3341 if (!(iterate_item = dewrap(iterate_item, US"\"\"")))
3342 {
3343 expand_string_message =
3344 string_sprintf("%s wrapping string result for extract jsons",
3345 expand_string_message);
3346 iterate_item = save_iterate_item;
3347 return NULL;
3348 }
3349
3350 DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", opname, iterate_item);
3351 if (!