readsocket expansion: response caching
[exim.git] / src / src / expand.c
1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8
9 /* Functions for handling string expansion. */
10
11
12 #include "exim.h"
13
14 /* Recursively called function */
15
16 static uschar *expand_string_internal(const uschar *, BOOL, const uschar **, BOOL, BOOL, BOOL *);
17 static int_eximarith_t expanded_string_integer(const uschar *, BOOL);
18
19 #ifdef STAND_ALONE
20 # ifndef SUPPORT_CRYPTEQ
21 # define SUPPORT_CRYPTEQ
22 # endif
23 #endif
24
25 #ifdef LOOKUP_LDAP
26 # include "lookups/ldap.h"
27 #endif
28
29 #ifdef SUPPORT_CRYPTEQ
30 # ifdef CRYPT_H
31 # include <crypt.h>
32 # endif
33 # ifndef HAVE_CRYPT16
34 extern char* crypt16(char*, char*);
35 # endif
36 #endif
37
38 /* The handling of crypt16() is a mess. I will record below the analysis of the
39 mess that was sent to me. We decided, however, to make changing this very low
40 priority, because in practice people are moving away from the crypt()
41 algorithms nowadays, so it doesn't seem worth it.
42
43 <quote>
44 There is an algorithm named "crypt16" in Ultrix and Tru64. It crypts
45 the first 8 characters of the password using a 20-round version of crypt
46 (standard crypt does 25 rounds). It then crypts the next 8 characters,
47 or an empty block if the password is less than 9 characters, using a
48 20-round version of crypt and the same salt as was used for the first
49 block. Characters after the first 16 are ignored. It always generates
50 a 16-byte hash, which is expressed together with the salt as a string
51 of 24 base 64 digits. Here are some links to peruse:
52
53 http://cvs.pld.org.pl/pam/pamcrypt/crypt16.c?rev=1.2
54 http://seclists.org/bugtraq/1999/Mar/0076.html
55
56 There's a different algorithm named "bigcrypt" in HP-UX, Digital Unix,
57 and OSF/1. This is the same as the standard crypt if given a password
58 of 8 characters or less. If given more, it first does the same as crypt
59 using the first 8 characters, then crypts the next 8 (the 9th to 16th)
60 using as salt the first two base 64 digits from the first hash block.
61 If the password is more than 16 characters then it crypts the 17th to 24th
62 characters using as salt the first two base 64 digits from the second hash
63 block. And so on: I've seen references to it cutting off the password at
64 40 characters (5 blocks), 80 (10 blocks), or 128 (16 blocks). Some links:
65
66 http://cvs.pld.org.pl/pam/pamcrypt/bigcrypt.c?rev=1.2
67 http://seclists.org/bugtraq/1999/Mar/0109.html
68 http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-Q0R2D-
69 TET1_html/sec.c222.html#no_id_208
70
71 Exim has something it calls "crypt16". It will either use a native
72 crypt16 or its own implementation. A native crypt16 will presumably
73 be the one that I called "crypt16" above. The internal "crypt16"
74 function, however, is a two-block-maximum implementation of what I called
75 "bigcrypt". The documentation matches the internal code.
76
77 I suspect that whoever did the "crypt16" stuff for Exim didn't realise
78 that crypt16 and bigcrypt were different things.
79
80 Exim uses the LDAP-style scheme identifier "{crypt16}" to refer
81 to whatever it is using under that name. This unfortunately sets a
82 precedent for using "{crypt16}" to identify two incompatible algorithms
83 whose output can't be distinguished. With "{crypt16}" thus rendered
84 ambiguous, I suggest you deprecate it and invent two new identifiers
85 for the two algorithms.
86
87 Both crypt16 and bigcrypt are very poor algorithms, btw. Hashing parts
88 of the password separately means they can be cracked separately, so
89 the double-length hash only doubles the cracking effort instead of
90 squaring it. I recommend salted SHA-1 ({SSHA}), or the Blowfish-based
91 bcrypt ({CRYPT}$2a$).
92 </quote>
93 */
94
95
96
97 /*************************************************
98 * Local statics and tables *
99 *************************************************/
100
101 /* Table of item names, and corresponding switch numbers. The names must be in
102 alphabetical order. */
103
104 static uschar *item_table[] = {
105 US"acl",
106 US"authresults",
107 US"certextract",
108 US"dlfunc",
109 US"env",
110 US"extract",
111 US"filter",
112 US"hash",
113 US"hmac",
114 US"if",
115 #ifdef SUPPORT_I18N
116 US"imapfolder",
117 #endif
118 US"length",
119 US"listextract",
120 US"listquote",
121 US"lookup",
122 US"map",
123 US"nhash",
124 US"perl",
125 US"prvs",
126 US"prvscheck",
127 US"readfile",
128 US"readsocket",
129 US"reduce",
130 US"run",
131 US"sg",
132 US"sort",
133 #ifdef EXPERIMENTAL_SRS_NATIVE
134 US"srs_encode",
135 #endif
136 US"substr",
137 US"tr" };
138
139 enum {
140 EITEM_ACL,
141 EITEM_AUTHRESULTS,
142 EITEM_CERTEXTRACT,
143 EITEM_DLFUNC,
144 EITEM_ENV,
145 EITEM_EXTRACT,
146 EITEM_FILTER,
147 EITEM_HASH,
148 EITEM_HMAC,
149 EITEM_IF,
150 #ifdef SUPPORT_I18N
151 EITEM_IMAPFOLDER,
152 #endif
153 EITEM_LENGTH,
154 EITEM_LISTEXTRACT,
155 EITEM_LISTQUOTE,
156 EITEM_LOOKUP,
157 EITEM_MAP,
158 EITEM_NHASH,
159 EITEM_PERL,
160 EITEM_PRVS,
161 EITEM_PRVSCHECK,
162 EITEM_READFILE,
163 EITEM_READSOCK,
164 EITEM_REDUCE,
165 EITEM_RUN,
166 EITEM_SG,
167 EITEM_SORT,
168 #ifdef EXPERIMENTAL_SRS_NATIVE
169 EITEM_SRS_ENCODE,
170 #endif
171 EITEM_SUBSTR,
172 EITEM_TR };
173
174 /* Tables of operator names, and corresponding switch numbers. The names must be
175 in alphabetical order. There are two tables, because underscore is used in some
176 cases to introduce arguments, whereas for other it is part of the name. This is
177 an historical mis-design. */
178
179 static uschar *op_table_underscore[] = {
180 US"from_utf8",
181 US"local_part",
182 US"quote_local_part",
183 US"reverse_ip",
184 US"time_eval",
185 US"time_interval"
186 #ifdef SUPPORT_I18N
187 ,US"utf8_domain_from_alabel",
188 US"utf8_domain_to_alabel",
189 US"utf8_localpart_from_alabel",
190 US"utf8_localpart_to_alabel"
191 #endif
192 };
193
194 enum {
195 EOP_FROM_UTF8,
196 EOP_LOCAL_PART,
197 EOP_QUOTE_LOCAL_PART,
198 EOP_REVERSE_IP,
199 EOP_TIME_EVAL,
200 EOP_TIME_INTERVAL
201 #ifdef SUPPORT_I18N
202 ,EOP_UTF8_DOMAIN_FROM_ALABEL,
203 EOP_UTF8_DOMAIN_TO_ALABEL,
204 EOP_UTF8_LOCALPART_FROM_ALABEL,
205 EOP_UTF8_LOCALPART_TO_ALABEL
206 #endif
207 };
208
209 static uschar *op_table_main[] = {
210 US"address",
211 US"addresses",
212 US"base32",
213 US"base32d",
214 US"base62",
215 US"base62d",
216 US"base64",
217 US"base64d",
218 US"bless",
219 US"domain",
220 US"escape",
221 US"escape8bit",
222 US"eval",
223 US"eval10",
224 US"expand",
225 US"h",
226 US"hash",
227 US"hex2b64",
228 US"hexquote",
229 US"ipv6denorm",
230 US"ipv6norm",
231 US"l",
232 US"lc",
233 US"length",
234 US"listcount",
235 US"listnamed",
236 US"mask",
237 US"md5",
238 US"nh",
239 US"nhash",
240 US"quote",
241 US"randint",
242 US"rfc2047",
243 US"rfc2047d",
244 US"rxquote",
245 US"s",
246 US"sha1",
247 US"sha2",
248 US"sha256",
249 US"sha3",
250 US"stat",
251 US"str2b64",
252 US"strlen",
253 US"substr",
254 US"uc",
255 US"utf8clean" };
256
257 enum {
258 EOP_ADDRESS = nelem(op_table_underscore),
259 EOP_ADDRESSES,
260 EOP_BASE32,
261 EOP_BASE32D,
262 EOP_BASE62,
263 EOP_BASE62D,
264 EOP_BASE64,
265 EOP_BASE64D,
266 EOP_BLESS,
267 EOP_DOMAIN,
268 EOP_ESCAPE,
269 EOP_ESCAPE8BIT,
270 EOP_EVAL,
271 EOP_EVAL10,
272 EOP_EXPAND,
273 EOP_H,
274 EOP_HASH,
275 EOP_HEX2B64,
276 EOP_HEXQUOTE,
277 EOP_IPV6DENORM,
278 EOP_IPV6NORM,
279 EOP_L,
280 EOP_LC,
281 EOP_LENGTH,
282 EOP_LISTCOUNT,
283 EOP_LISTNAMED,
284 EOP_MASK,
285 EOP_MD5,
286 EOP_NH,
287 EOP_NHASH,
288 EOP_QUOTE,
289 EOP_RANDINT,
290 EOP_RFC2047,
291 EOP_RFC2047D,
292 EOP_RXQUOTE,
293 EOP_S,
294 EOP_SHA1,
295 EOP_SHA2,
296 EOP_SHA256,
297 EOP_SHA3,
298 EOP_STAT,
299 EOP_STR2B64,
300 EOP_STRLEN,
301 EOP_SUBSTR,
302 EOP_UC,
303 EOP_UTF8CLEAN };
304
305
306 /* Table of condition names, and corresponding switch numbers. The names must
307 be in alphabetical order. */
308
309 static uschar *cond_table[] = {
310 US"<",
311 US"<=",
312 US"=",
313 US"==", /* Backward compatibility */
314 US">",
315 US">=",
316 US"acl",
317 US"and",
318 US"bool",
319 US"bool_lax",
320 US"crypteq",
321 US"def",
322 US"eq",
323 US"eqi",
324 US"exists",
325 US"first_delivery",
326 US"forall",
327 US"forall_json",
328 US"forall_jsons",
329 US"forany",
330 US"forany_json",
331 US"forany_jsons",
332 US"ge",
333 US"gei",
334 US"gt",
335 US"gti",
336 #ifdef EXPERIMENTAL_SRS_NATIVE
337 US"inbound_srs",
338 #endif
339 US"inlist",
340 US"inlisti",
341 US"isip",
342 US"isip4",
343 US"isip6",
344 US"ldapauth",
345 US"le",
346 US"lei",
347 US"lt",
348 US"lti",
349 US"match",
350 US"match_address",
351 US"match_domain",
352 US"match_ip",
353 US"match_local_part",
354 US"or",
355 US"pam",
356 US"pwcheck",
357 US"queue_running",
358 US"radius",
359 US"saslauthd"
360 };
361
362 enum {
363 ECOND_NUM_L,
364 ECOND_NUM_LE,
365 ECOND_NUM_E,
366 ECOND_NUM_EE,
367 ECOND_NUM_G,
368 ECOND_NUM_GE,
369 ECOND_ACL,
370 ECOND_AND,
371 ECOND_BOOL,
372 ECOND_BOOL_LAX,
373 ECOND_CRYPTEQ,
374 ECOND_DEF,
375 ECOND_STR_EQ,
376 ECOND_STR_EQI,
377 ECOND_EXISTS,
378 ECOND_FIRST_DELIVERY,
379 ECOND_FORALL,
380 ECOND_FORALL_JSON,
381 ECOND_FORALL_JSONS,
382 ECOND_FORANY,
383 ECOND_FORANY_JSON,
384 ECOND_FORANY_JSONS,
385 ECOND_STR_GE,
386 ECOND_STR_GEI,
387 ECOND_STR_GT,
388 ECOND_STR_GTI,
389 #ifdef EXPERIMENTAL_SRS_NATIVE
390 ECOND_INBOUND_SRS,
391 #endif
392 ECOND_INLIST,
393 ECOND_INLISTI,
394 ECOND_ISIP,
395 ECOND_ISIP4,
396 ECOND_ISIP6,
397 ECOND_LDAPAUTH,
398 ECOND_STR_LE,
399 ECOND_STR_LEI,
400 ECOND_STR_LT,
401 ECOND_STR_LTI,
402 ECOND_MATCH,
403 ECOND_MATCH_ADDRESS,
404 ECOND_MATCH_DOMAIN,
405 ECOND_MATCH_IP,
406 ECOND_MATCH_LOCAL_PART,
407 ECOND_OR,
408 ECOND_PAM,
409 ECOND_PWCHECK,
410 ECOND_QUEUE_RUNNING,
411 ECOND_RADIUS,
412 ECOND_SASLAUTHD
413 };
414
415
416 /* Types of table entry */
417
418 enum vtypes {
419 vtype_int, /* value is address of int */
420 vtype_filter_int, /* ditto, but recognized only when filtering */
421 vtype_ino, /* value is address of ino_t (not always an int) */
422 vtype_uid, /* value is address of uid_t (not always an int) */
423 vtype_gid, /* value is address of gid_t (not always an int) */
424 vtype_bool, /* value is address of bool */
425 vtype_stringptr, /* value is address of pointer to string */
426 vtype_msgbody, /* as stringptr, but read when first required */
427 vtype_msgbody_end, /* ditto, the end of the message */
428 vtype_msgheaders, /* the message's headers, processed */
429 vtype_msgheaders_raw, /* the message's headers, unprocessed */
430 vtype_localpart, /* extract local part from string */
431 vtype_domain, /* extract domain from string */
432 vtype_string_func, /* value is string returned by given function */
433 vtype_todbsdin, /* value not used; generate BSD inbox tod */
434 vtype_tode, /* value not used; generate tod in epoch format */
435 vtype_todel, /* value not used; generate tod in epoch/usec format */
436 vtype_todf, /* value not used; generate full tod */
437 vtype_todl, /* value not used; generate log tod */
438 vtype_todlf, /* value not used; generate log file datestamp tod */
439 vtype_todzone, /* value not used; generate time zone only */
440 vtype_todzulu, /* value not used; generate zulu tod */
441 vtype_reply, /* value not used; get reply from headers */
442 vtype_pid, /* value not used; result is pid */
443 vtype_host_lookup, /* value not used; get host name */
444 vtype_load_avg, /* value not used; result is int from os_getloadavg */
445 vtype_pspace, /* partition space; value is T/F for spool/log */
446 vtype_pinodes, /* partition inodes; value is T/F for spool/log */
447 vtype_cert /* SSL certificate */
448 #ifndef DISABLE_DKIM
449 ,vtype_dkim /* Lookup of value in DKIM signature */
450 #endif
451 };
452
453 /* Type for main variable table */
454
455 typedef struct {
456 const char *name;
457 enum vtypes type;
458 void *value;
459 } var_entry;
460
461 /* Type for entries pointing to address/length pairs. Not currently
462 in use. */
463
464 typedef struct {
465 uschar **address;
466 int *length;
467 } alblock;
468
469 static uschar * fn_recipients(void);
470 typedef uschar * stringptr_fn_t(void);
471 static uschar * fn_queue_size(void);
472
473 /* This table must be kept in alphabetical order. */
474
475 static var_entry var_table[] = {
476 /* WARNING: Do not invent variables whose names start acl_c or acl_m because
477 they will be confused with user-creatable ACL variables. */
478 { "acl_arg1", vtype_stringptr, &acl_arg[0] },
479 { "acl_arg2", vtype_stringptr, &acl_arg[1] },
480 { "acl_arg3", vtype_stringptr, &acl_arg[2] },
481 { "acl_arg4", vtype_stringptr, &acl_arg[3] },
482 { "acl_arg5", vtype_stringptr, &acl_arg[4] },
483 { "acl_arg6", vtype_stringptr, &acl_arg[5] },
484 { "acl_arg7", vtype_stringptr, &acl_arg[6] },
485 { "acl_arg8", vtype_stringptr, &acl_arg[7] },
486 { "acl_arg9", vtype_stringptr, &acl_arg[8] },
487 { "acl_narg", vtype_int, &acl_narg },
488 { "acl_verify_message", vtype_stringptr, &acl_verify_message },
489 { "address_data", vtype_stringptr, &deliver_address_data },
490 { "address_file", vtype_stringptr, &address_file },
491 { "address_pipe", vtype_stringptr, &address_pipe },
492 #ifdef EXPERIMENTAL_ARC
493 { "arc_domains", vtype_string_func, (void *) &fn_arc_domains },
494 { "arc_oldest_pass", vtype_int, &arc_oldest_pass },
495 { "arc_state", vtype_stringptr, &arc_state },
496 { "arc_state_reason", vtype_stringptr, &arc_state_reason },
497 #endif
498 { "authenticated_fail_id",vtype_stringptr, &authenticated_fail_id },
499 { "authenticated_id", vtype_stringptr, &authenticated_id },
500 { "authenticated_sender",vtype_stringptr, &authenticated_sender },
501 { "authentication_failed",vtype_int, &authentication_failed },
502 #ifdef WITH_CONTENT_SCAN
503 { "av_failed", vtype_int, &av_failed },
504 #endif
505 #ifdef EXPERIMENTAL_BRIGHTMAIL
506 { "bmi_alt_location", vtype_stringptr, &bmi_alt_location },
507 { "bmi_base64_tracker_verdict", vtype_stringptr, &bmi_base64_tracker_verdict },
508 { "bmi_base64_verdict", vtype_stringptr, &bmi_base64_verdict },
509 { "bmi_deliver", vtype_int, &bmi_deliver },
510 #endif
511 { "body_linecount", vtype_int, &body_linecount },
512 { "body_zerocount", vtype_int, &body_zerocount },
513 { "bounce_recipient", vtype_stringptr, &bounce_recipient },
514 { "bounce_return_size_limit", vtype_int, &bounce_return_size_limit },
515 { "caller_gid", vtype_gid, &real_gid },
516 { "caller_uid", vtype_uid, &real_uid },
517 { "callout_address", vtype_stringptr, &callout_address },
518 { "compile_date", vtype_stringptr, &version_date },
519 { "compile_number", vtype_stringptr, &version_cnumber },
520 { "config_dir", vtype_stringptr, &config_main_directory },
521 { "config_file", vtype_stringptr, &config_main_filename },
522 { "csa_status", vtype_stringptr, &csa_status },
523 #ifdef EXPERIMENTAL_DCC
524 { "dcc_header", vtype_stringptr, &dcc_header },
525 { "dcc_result", vtype_stringptr, &dcc_result },
526 #endif
527 #ifndef DISABLE_DKIM
528 { "dkim_algo", vtype_dkim, (void *)DKIM_ALGO },
529 { "dkim_bodylength", vtype_dkim, (void *)DKIM_BODYLENGTH },
530 { "dkim_canon_body", vtype_dkim, (void *)DKIM_CANON_BODY },
531 { "dkim_canon_headers", vtype_dkim, (void *)DKIM_CANON_HEADERS },
532 { "dkim_copiedheaders", vtype_dkim, (void *)DKIM_COPIEDHEADERS },
533 { "dkim_created", vtype_dkim, (void *)DKIM_CREATED },
534 { "dkim_cur_signer", vtype_stringptr, &dkim_cur_signer },
535 { "dkim_domain", vtype_stringptr, &dkim_signing_domain },
536 { "dkim_expires", vtype_dkim, (void *)DKIM_EXPIRES },
537 { "dkim_headernames", vtype_dkim, (void *)DKIM_HEADERNAMES },
538 { "dkim_identity", vtype_dkim, (void *)DKIM_IDENTITY },
539 { "dkim_key_granularity",vtype_dkim, (void *)DKIM_KEY_GRANULARITY },
540 { "dkim_key_length", vtype_int, &dkim_key_length },
541 { "dkim_key_nosubdomains",vtype_dkim, (void *)DKIM_NOSUBDOMAINS },
542 { "dkim_key_notes", vtype_dkim, (void *)DKIM_KEY_NOTES },
543 { "dkim_key_srvtype", vtype_dkim, (void *)DKIM_KEY_SRVTYPE },
544 { "dkim_key_testing", vtype_dkim, (void *)DKIM_KEY_TESTING },
545 { "dkim_selector", vtype_stringptr, &dkim_signing_selector },
546 { "dkim_signers", vtype_stringptr, &dkim_signers },
547 { "dkim_verify_reason", vtype_stringptr, &dkim_verify_reason },
548 { "dkim_verify_status", vtype_stringptr, &dkim_verify_status },
549 #endif
550 #ifdef SUPPORT_DMARC
551 { "dmarc_domain_policy", vtype_stringptr, &dmarc_domain_policy },
552 { "dmarc_status", vtype_stringptr, &dmarc_status },
553 { "dmarc_status_text", vtype_stringptr, &dmarc_status_text },
554 { "dmarc_used_domain", vtype_stringptr, &dmarc_used_domain },
555 #endif
556 { "dnslist_domain", vtype_stringptr, &dnslist_domain },
557 { "dnslist_matched", vtype_stringptr, &dnslist_matched },
558 { "dnslist_text", vtype_stringptr, &dnslist_text },
559 { "dnslist_value", vtype_stringptr, &dnslist_value },
560 { "domain", vtype_stringptr, &deliver_domain },
561 { "domain_data", vtype_stringptr, &deliver_domain_data },
562 #ifndef DISABLE_EVENT
563 { "event_data", vtype_stringptr, &event_data },
564
565 /*XXX want to use generic vars for as many of these as possible*/
566 { "event_defer_errno", vtype_int, &event_defer_errno },
567
568 { "event_name", vtype_stringptr, &event_name },
569 #endif
570 { "exim_gid", vtype_gid, &exim_gid },
571 { "exim_path", vtype_stringptr, &exim_path },
572 { "exim_uid", vtype_uid, &exim_uid },
573 { "exim_version", vtype_stringptr, &version_string },
574 { "headers_added", vtype_string_func, (void *) &fn_hdrs_added },
575 { "home", vtype_stringptr, &deliver_home },
576 { "host", vtype_stringptr, &deliver_host },
577 { "host_address", vtype_stringptr, &deliver_host_address },
578 { "host_data", vtype_stringptr, &host_data },
579 { "host_lookup_deferred",vtype_int, &host_lookup_deferred },
580 { "host_lookup_failed", vtype_int, &host_lookup_failed },
581 { "host_port", vtype_int, &deliver_host_port },
582 { "initial_cwd", vtype_stringptr, &initial_cwd },
583 { "inode", vtype_ino, &deliver_inode },
584 { "interface_address", vtype_stringptr, &interface_address },
585 { "interface_port", vtype_int, &interface_port },
586 { "item", vtype_stringptr, &iterate_item },
587 #ifdef LOOKUP_LDAP
588 { "ldap_dn", vtype_stringptr, &eldap_dn },
589 #endif
590 { "load_average", vtype_load_avg, NULL },
591 { "local_part", vtype_stringptr, &deliver_localpart },
592 { "local_part_data", vtype_stringptr, &deliver_localpart_data },
593 { "local_part_prefix", vtype_stringptr, &deliver_localpart_prefix },
594 { "local_part_prefix_v", vtype_stringptr, &deliver_localpart_prefix_v },
595 { "local_part_suffix", vtype_stringptr, &deliver_localpart_suffix },
596 { "local_part_suffix_v", vtype_stringptr, &deliver_localpart_suffix_v },
597 { "local_part_verified", vtype_stringptr, &deliver_localpart_verified },
598 #ifdef HAVE_LOCAL_SCAN
599 { "local_scan_data", vtype_stringptr, &local_scan_data },
600 #endif
601 { "local_user_gid", vtype_gid, &local_user_gid },
602 { "local_user_uid", vtype_uid, &local_user_uid },
603 { "localhost_number", vtype_int, &host_number },
604 { "log_inodes", vtype_pinodes, (void *)FALSE },
605 { "log_space", vtype_pspace, (void *)FALSE },
606 { "lookup_dnssec_authenticated",vtype_stringptr,&lookup_dnssec_authenticated},
607 { "mailstore_basename", vtype_stringptr, &mailstore_basename },
608 #ifdef WITH_CONTENT_SCAN
609 { "malware_name", vtype_stringptr, &malware_name },
610 #endif
611 { "max_received_linelength", vtype_int, &max_received_linelength },
612 { "message_age", vtype_int, &message_age },
613 { "message_body", vtype_msgbody, &message_body },
614 { "message_body_end", vtype_msgbody_end, &message_body_end },
615 { "message_body_size", vtype_int, &message_body_size },
616 { "message_exim_id", vtype_stringptr, &message_id },
617 { "message_headers", vtype_msgheaders, NULL },
618 { "message_headers_raw", vtype_msgheaders_raw, NULL },
619 { "message_id", vtype_stringptr, &message_id },
620 { "message_linecount", vtype_int, &message_linecount },
621 { "message_size", vtype_int, &message_size },
622 #ifdef SUPPORT_I18N
623 { "message_smtputf8", vtype_bool, &message_smtputf8 },
624 #endif
625 #ifdef WITH_CONTENT_SCAN
626 { "mime_anomaly_level", vtype_int, &mime_anomaly_level },
627 { "mime_anomaly_text", vtype_stringptr, &mime_anomaly_text },
628 { "mime_boundary", vtype_stringptr, &mime_boundary },
629 { "mime_charset", vtype_stringptr, &mime_charset },
630 { "mime_content_description", vtype_stringptr, &mime_content_description },
631 { "mime_content_disposition", vtype_stringptr, &mime_content_disposition },
632 { "mime_content_id", vtype_stringptr, &mime_content_id },
633 { "mime_content_size", vtype_int, &mime_content_size },
634 { "mime_content_transfer_encoding",vtype_stringptr, &mime_content_transfer_encoding },
635 { "mime_content_type", vtype_stringptr, &mime_content_type },
636 { "mime_decoded_filename", vtype_stringptr, &mime_decoded_filename },
637 { "mime_filename", vtype_stringptr, &mime_filename },
638 { "mime_is_coverletter", vtype_int, &mime_is_coverletter },
639 { "mime_is_multipart", vtype_int, &mime_is_multipart },
640 { "mime_is_rfc822", vtype_int, &mime_is_rfc822 },
641 { "mime_part_count", vtype_int, &mime_part_count },
642 #endif
643 { "n0", vtype_filter_int, &filter_n[0] },
644 { "n1", vtype_filter_int, &filter_n[1] },
645 { "n2", vtype_filter_int, &filter_n[2] },
646 { "n3", vtype_filter_int, &filter_n[3] },
647 { "n4", vtype_filter_int, &filter_n[4] },
648 { "n5", vtype_filter_int, &filter_n[5] },
649 { "n6", vtype_filter_int, &filter_n[6] },
650 { "n7", vtype_filter_int, &filter_n[7] },
651 { "n8", vtype_filter_int, &filter_n[8] },
652 { "n9", vtype_filter_int, &filter_n[9] },
653 { "original_domain", vtype_stringptr, &deliver_domain_orig },
654 { "original_local_part", vtype_stringptr, &deliver_localpart_orig },
655 { "originator_gid", vtype_gid, &originator_gid },
656 { "originator_uid", vtype_uid, &originator_uid },
657 { "parent_domain", vtype_stringptr, &deliver_domain_parent },
658 { "parent_local_part", vtype_stringptr, &deliver_localpart_parent },
659 { "pid", vtype_pid, NULL },
660 #ifndef DISABLE_PRDR
661 { "prdr_requested", vtype_bool, &prdr_requested },
662 #endif
663 { "primary_hostname", vtype_stringptr, &primary_hostname },
664 #if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
665 { "proxy_external_address",vtype_stringptr, &proxy_external_address },
666 { "proxy_external_port", vtype_int, &proxy_external_port },
667 { "proxy_local_address", vtype_stringptr, &proxy_local_address },
668 { "proxy_local_port", vtype_int, &proxy_local_port },
669 { "proxy_session", vtype_bool, &proxy_session },
670 #endif
671 { "prvscheck_address", vtype_stringptr, &prvscheck_address },
672 { "prvscheck_keynum", vtype_stringptr, &prvscheck_keynum },
673 { "prvscheck_result", vtype_stringptr, &prvscheck_result },
674 { "qualify_domain", vtype_stringptr, &qualify_domain_sender },
675 { "qualify_recipient", vtype_stringptr, &qualify_domain_recipient },
676 { "queue_name", vtype_stringptr, &queue_name },
677 { "queue_size", vtype_string_func, &fn_queue_size },
678 { "rcpt_count", vtype_int, &rcpt_count },
679 { "rcpt_defer_count", vtype_int, &rcpt_defer_count },
680 { "rcpt_fail_count", vtype_int, &rcpt_fail_count },
681 { "received_count", vtype_int, &received_count },
682 { "received_for", vtype_stringptr, &received_for },
683 { "received_ip_address", vtype_stringptr, &interface_address },
684 { "received_port", vtype_int, &interface_port },
685 { "received_protocol", vtype_stringptr, &received_protocol },
686 { "received_time", vtype_int, &received_time.tv_sec },
687 { "recipient_data", vtype_stringptr, &recipient_data },
688 { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
689 { "recipients", vtype_string_func, (void *) &fn_recipients },
690 { "recipients_count", vtype_int, &recipients_count },
691 #ifdef WITH_CONTENT_SCAN
692 { "regex_match_string", vtype_stringptr, &regex_match_string },
693 #endif
694 { "reply_address", vtype_reply, NULL },
695 { "return_path", vtype_stringptr, &return_path },
696 { "return_size_limit", vtype_int, &bounce_return_size_limit },
697 { "router_name", vtype_stringptr, &router_name },
698 { "runrc", vtype_int, &runrc },
699 { "self_hostname", vtype_stringptr, &self_hostname },
700 { "sender_address", vtype_stringptr, &sender_address },
701 { "sender_address_data", vtype_stringptr, &sender_address_data },
702 { "sender_address_domain", vtype_domain, &sender_address },
703 { "sender_address_local_part", vtype_localpart, &sender_address },
704 { "sender_data", vtype_stringptr, &sender_data },
705 { "sender_fullhost", vtype_stringptr, &sender_fullhost },
706 { "sender_helo_dnssec", vtype_bool, &sender_helo_dnssec },
707 { "sender_helo_name", vtype_stringptr, &sender_helo_name },
708 { "sender_host_address", vtype_stringptr, &sender_host_address },
709 { "sender_host_authenticated",vtype_stringptr, &sender_host_authenticated },
710 { "sender_host_dnssec", vtype_bool, &sender_host_dnssec },
711 { "sender_host_name", vtype_host_lookup, NULL },
712 { "sender_host_port", vtype_int, &sender_host_port },
713 { "sender_ident", vtype_stringptr, &sender_ident },
714 { "sender_rate", vtype_stringptr, &sender_rate },
715 { "sender_rate_limit", vtype_stringptr, &sender_rate_limit },
716 { "sender_rate_period", vtype_stringptr, &sender_rate_period },
717 { "sender_rcvhost", vtype_stringptr, &sender_rcvhost },
718 { "sender_verify_failure",vtype_stringptr, &sender_verify_failure },
719 { "sending_ip_address", vtype_stringptr, &sending_ip_address },
720 { "sending_port", vtype_int, &sending_port },
721 { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname },
722 { "smtp_command", vtype_stringptr, &smtp_cmd_buffer },
723 { "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument },
724 { "smtp_command_history", vtype_string_func, (void *) &smtp_cmd_hist },
725 { "smtp_count_at_connection_start", vtype_int, &smtp_accept_count },
726 { "smtp_notquit_reason", vtype_stringptr, &smtp_notquit_reason },
727 { "sn0", vtype_filter_int, &filter_sn[0] },
728 { "sn1", vtype_filter_int, &filter_sn[1] },
729 { "sn2", vtype_filter_int, &filter_sn[2] },
730 { "sn3", vtype_filter_int, &filter_sn[3] },
731 { "sn4", vtype_filter_int, &filter_sn[4] },
732 { "sn5", vtype_filter_int, &filter_sn[5] },
733 { "sn6", vtype_filter_int, &filter_sn[6] },
734 { "sn7", vtype_filter_int, &filter_sn[7] },
735 { "sn8", vtype_filter_int, &filter_sn[8] },
736 { "sn9", vtype_filter_int, &filter_sn[9] },
737 #ifdef WITH_CONTENT_SCAN
738 { "spam_action", vtype_stringptr, &spam_action },
739 { "spam_bar", vtype_stringptr, &spam_bar },
740 { "spam_report", vtype_stringptr, &spam_report },
741 { "spam_score", vtype_stringptr, &spam_score },
742 { "spam_score_int", vtype_stringptr, &spam_score_int },
743 #endif
744 #ifdef SUPPORT_SPF
745 { "spf_guess", vtype_stringptr, &spf_guess },
746 { "spf_header_comment", vtype_stringptr, &spf_header_comment },
747 { "spf_received", vtype_stringptr, &spf_received },
748 { "spf_result", vtype_stringptr, &spf_result },
749 { "spf_result_guessed", vtype_bool, &spf_result_guessed },
750 { "spf_smtp_comment", vtype_stringptr, &spf_smtp_comment },
751 #endif
752 { "spool_directory", vtype_stringptr, &spool_directory },
753 { "spool_inodes", vtype_pinodes, (void *)TRUE },
754 { "spool_space", vtype_pspace, (void *)TRUE },
755 #ifdef EXPERIMENTAL_SRS
756 { "srs_db_address", vtype_stringptr, &srs_db_address },
757 { "srs_db_key", vtype_stringptr, &srs_db_key },
758 { "srs_orig_recipient", vtype_stringptr, &srs_orig_recipient },
759 { "srs_orig_sender", vtype_stringptr, &srs_orig_sender },
760 #endif
761 #if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
762 { "srs_recipient", vtype_stringptr, &srs_recipient },
763 #endif
764 #ifdef EXPERIMENTAL_SRS
765 { "srs_status", vtype_stringptr, &srs_status },
766 #endif
767 { "thisaddress", vtype_stringptr, &filter_thisaddress },
768
769 /* The non-(in,out) variables are now deprecated */
770 { "tls_bits", vtype_int, &tls_in.bits },
771 { "tls_certificate_verified", vtype_int, &tls_in.certificate_verified },
772 { "tls_cipher", vtype_stringptr, &tls_in.cipher },
773
774 { "tls_in_bits", vtype_int, &tls_in.bits },
775 { "tls_in_certificate_verified", vtype_int, &tls_in.certificate_verified },
776 { "tls_in_cipher", vtype_stringptr, &tls_in.cipher },
777 { "tls_in_cipher_std", vtype_stringptr, &tls_in.cipher_stdname },
778 { "tls_in_ocsp", vtype_int, &tls_in.ocsp },
779 { "tls_in_ourcert", vtype_cert, &tls_in.ourcert },
780 { "tls_in_peercert", vtype_cert, &tls_in.peercert },
781 { "tls_in_peerdn", vtype_stringptr, &tls_in.peerdn },
782 #ifdef EXPERIMENTAL_TLS_RESUME
783 { "tls_in_resumption", vtype_int, &tls_in.resumption },
784 #endif
785 #ifndef DISABLE_TLS
786 { "tls_in_sni", vtype_stringptr, &tls_in.sni },
787 #endif
788 { "tls_in_ver", vtype_stringptr, &tls_in.ver },
789 { "tls_out_bits", vtype_int, &tls_out.bits },
790 { "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified },
791 { "tls_out_cipher", vtype_stringptr, &tls_out.cipher },
792 { "tls_out_cipher_std", vtype_stringptr, &tls_out.cipher_stdname },
793 #ifdef SUPPORT_DANE
794 { "tls_out_dane", vtype_bool, &tls_out.dane_verified },
795 #endif
796 { "tls_out_ocsp", vtype_int, &tls_out.ocsp },
797 { "tls_out_ourcert", vtype_cert, &tls_out.ourcert },
798 { "tls_out_peercert", vtype_cert, &tls_out.peercert },
799 { "tls_out_peerdn", vtype_stringptr, &tls_out.peerdn },
800 #ifdef EXPERIMENTAL_TLS_RESUME
801 { "tls_out_resumption", vtype_int, &tls_out.resumption },
802 #endif
803 #ifndef DISABLE_TLS
804 { "tls_out_sni", vtype_stringptr, &tls_out.sni },
805 #endif
806 #ifdef SUPPORT_DANE
807 { "tls_out_tlsa_usage", vtype_int, &tls_out.tlsa_usage },
808 #endif
809 { "tls_out_ver", vtype_stringptr, &tls_out.ver },
810
811 { "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, /* mind the alphabetical order! */
812 #ifndef DISABLE_TLS
813 { "tls_sni", vtype_stringptr, &tls_in.sni }, /* mind the alphabetical order! */
814 #endif
815
816 { "tod_bsdinbox", vtype_todbsdin, NULL },
817 { "tod_epoch", vtype_tode, NULL },
818 { "tod_epoch_l", vtype_todel, NULL },
819 { "tod_full", vtype_todf, NULL },
820 { "tod_log", vtype_todl, NULL },
821 { "tod_logfile", vtype_todlf, NULL },
822 { "tod_zone", vtype_todzone, NULL },
823 { "tod_zulu", vtype_todzulu, NULL },
824 { "transport_name", vtype_stringptr, &transport_name },
825 { "value", vtype_stringptr, &lookup_value },
826 { "verify_mode", vtype_stringptr, &verify_mode },
827 { "version_number", vtype_stringptr, &version_string },
828 { "warn_message_delay", vtype_stringptr, &warnmsg_delay },
829 { "warn_message_recipient",vtype_stringptr, &warnmsg_recipients },
830 { "warn_message_recipients",vtype_stringptr,&warnmsg_recipients },
831 { "warnmsg_delay", vtype_stringptr, &warnmsg_delay },
832 { "warnmsg_recipient", vtype_stringptr, &warnmsg_recipients },
833 { "warnmsg_recipients", vtype_stringptr, &warnmsg_recipients }
834 };
835
836 static int var_table_size = nelem(var_table);
837 static uschar var_buffer[256];
838 static BOOL malformed_header;
839
840 /* For textual hashes */
841
842 static const char *hashcodes = "abcdefghijklmnopqrtsuvwxyz"
843 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
844 "0123456789";
845
846 enum { HMAC_MD5, HMAC_SHA1 };
847
848 /* For numeric hashes */
849
850 static unsigned int prime[] = {
851 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
852 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
853 73, 79, 83, 89, 97, 101, 103, 107, 109, 113};
854
855 /* For printing modes in symbolic form */
856
857 static uschar *mtable_normal[] =
858 { US"---", US"--x", US"-w-", US"-wx", US"r--", US"r-x", US"rw-", US"rwx" };
859
860 static uschar *mtable_setid[] =
861 { US"--S", US"--s", US"-wS", US"-ws", US"r-S", US"r-s", US"rwS", US"rws" };
862
863 static uschar *mtable_sticky[] =
864 { US"--T", US"--t", US"-wT", US"-wt", US"r-T", US"r-t", US"rwT", US"rwt" };
865
866 /* flags for find_header() */
867 #define FH_EXISTS_ONLY BIT(0)
868 #define FH_WANT_RAW BIT(1)
869 #define FH_WANT_LIST BIT(2)
870
871
872 /*************************************************
873 * Tables for UTF-8 support *
874 *************************************************/
875
876 /* Table of the number of extra characters, indexed by the first character
877 masked with 0x3f. The highest number for a valid UTF-8 character is in fact
878 0x3d. */
879
880 static uschar utf8_table1[] = {
881 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
882 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
883 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
884 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
885
886 /* These are the masks for the data bits in the first byte of a character,
887 indexed by the number of additional bytes. */
888
889 static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
890
891 /* Get the next UTF-8 character, advancing the pointer. */
892
893 #define GETUTF8INC(c, ptr) \
894 c = *ptr++; \
895 if ((c & 0xc0) == 0xc0) \
896 { \
897 int a = utf8_table1[c & 0x3f]; /* Number of additional bytes */ \
898 int s = 6*a; \
899 c = (c & utf8_table2[a]) << s; \
900 while (a-- > 0) \
901 { \
902 s -= 6; \
903 c |= (*ptr++ & 0x3f) << s; \
904 } \
905 }
906
907
908
909 static uschar * base32_chars = US"abcdefghijklmnopqrstuvwxyz234567";
910
911 /*************************************************
912 * Binary chop search on a table *
913 *************************************************/
914
915 /* This is used for matching expansion items and operators.
916
917 Arguments:
918 name the name that is being sought
919 table the table to search
920 table_size the number of items in the table
921
922 Returns: the offset in the table, or -1
923 */
924
925 static int
926 chop_match(uschar *name, uschar **table, int table_size)
927 {
928 uschar **bot = table;
929 uschar **top = table + table_size;
930
931 while (top > bot)
932 {
933 uschar **mid = bot + (top - bot)/2;
934 int c = Ustrcmp(name, *mid);
935 if (c == 0) return mid - table;
936 if (c > 0) bot = mid + 1; else top = mid;
937 }
938
939 return -1;
940 }
941
942
943
944 /*************************************************
945 * Check a condition string *
946 *************************************************/
947
948 /* This function is called to expand a string, and test the result for a "true"
949 or "false" value. Failure of the expansion yields FALSE; logged unless it was a
950 forced fail or lookup defer.
951
952 We used to release all store used, but this is not not safe due
953 to ${dlfunc } and ${acl }. In any case expand_string_internal()
954 is reasonably careful to release what it can.
955
956 The actual false-value tests should be replicated for ECOND_BOOL_LAX.
957
958 Arguments:
959 condition the condition string
960 m1 text to be incorporated in panic error
961 m2 ditto
962
963 Returns: TRUE if condition is met, FALSE if not
964 */
965
966 BOOL
967 expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
968 {
969 uschar * ss = expand_string(condition);
970 if (!ss)
971 {
972 if (!f.expand_string_forcedfail && !f.search_find_defer)
973 log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand condition \"%s\" "
974 "for %s %s: %s", condition, m1, m2, expand_string_message);
975 return FALSE;
976 }
977 return *ss && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
978 strcmpic(ss, US"false") != 0;
979 }
980
981
982
983
984 /*************************************************
985 * Pseudo-random number generation *
986 *************************************************/
987
988 /* Pseudo-random number generation. The result is not "expected" to be
989 cryptographically strong but not so weak that someone will shoot themselves
990 in the foot using it as a nonce in some email header scheme or whatever
991 weirdness they'll twist this into. The result should ideally handle fork().
992
993 However, if we're stuck unable to provide this, then we'll fall back to
994 appallingly bad randomness.
995
996 If DISABLE_TLS is not defined then this will not be used except as an emergency
997 fallback.
998
999 Arguments:
1000 max range maximum
1001 Returns a random number in range [0, max-1]
1002 */
1003
1004 #ifndef DISABLE_TLS
1005 # define vaguely_random_number vaguely_random_number_fallback
1006 #endif
1007 int
1008 vaguely_random_number(int max)
1009 {
1010 #ifndef DISABLE_TLS
1011 # undef vaguely_random_number
1012 #endif
1013 static pid_t pid = 0;
1014 pid_t p2;
1015
1016 if ((p2 = getpid()) != pid)
1017 {
1018 if (pid != 0)
1019 {
1020
1021 #ifdef HAVE_ARC4RANDOM
1022 /* cryptographically strong randomness, common on *BSD platforms, not
1023 so much elsewhere. Alas. */
1024 # ifndef NOT_HAVE_ARC4RANDOM_STIR
1025 arc4random_stir();
1026 # endif
1027 #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
1028 # ifdef HAVE_SRANDOMDEV
1029 /* uses random(4) for seeding */
1030 srandomdev();
1031 # else
1032 {
1033 struct timeval tv;
1034 gettimeofday(&tv, NULL);
1035 srandom(tv.tv_sec | tv.tv_usec | getpid());
1036 }
1037 # endif
1038 #else
1039 /* Poor randomness and no seeding here */
1040 #endif
1041
1042 }
1043 pid = p2;
1044 }
1045
1046 #ifdef HAVE_ARC4RANDOM
1047 return arc4random() % max;
1048 #elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
1049 return random() % max;
1050 #else
1051 /* This one returns a 16-bit number, definitely not crypto-strong */
1052 return random_number(max);
1053 #endif
1054 }
1055
1056
1057
1058
1059 /*************************************************
1060 * Pick out a name from a string *
1061 *************************************************/
1062
1063 /* If the name is too long, it is silently truncated.
1064
1065 Arguments:
1066 name points to a buffer into which to put the name
1067 max is the length of the buffer
1068 s points to the first alphabetic character of the name
1069 extras chars other than alphanumerics to permit
1070
1071 Returns: pointer to the first character after the name
1072
1073 Note: The test for *s != 0 in the while loop is necessary because
1074 Ustrchr() yields non-NULL if the character is zero (which is not something
1075 I expected). */
1076
1077 static const uschar *
1078 read_name(uschar *name, int max, const uschar *s, uschar *extras)
1079 {
1080 int ptr = 0;
1081 while (*s && (isalnum(*s) || Ustrchr(extras, *s) != NULL))
1082 {
1083 if (ptr < max-1) name[ptr++] = *s;
1084 s++;
1085 }
1086 name[ptr] = 0;
1087 return s;
1088 }
1089
1090
1091
1092 /*************************************************
1093 * Pick out the rest of a header name *
1094 *************************************************/
1095
1096 /* A variable name starting $header_ (or just $h_ for those who like
1097 abbreviations) might not be the complete header name because headers can
1098 contain any printing characters in their names, except ':'. This function is
1099 called to read the rest of the name, chop h[eader]_ off the front, and put ':'
1100 on the end, if the name was terminated by white space.
1101
1102 Arguments:
1103 name points to a buffer in which the name read so far exists
1104 max is the length of the buffer
1105 s points to the first character after the name so far, i.e. the
1106 first non-alphameric character after $header_xxxxx
1107
1108 Returns: a pointer to the first character after the header name
1109 */
1110
1111 static const uschar *
1112 read_header_name(uschar *name, int max, const uschar *s)
1113 {
1114 int prelen = Ustrchr(name, '_') - name + 1;
1115 int ptr = Ustrlen(name) - prelen;
1116 if (ptr > 0) memmove(name, name+prelen, ptr);
1117 while (mac_isgraph(*s) && *s != ':')
1118 {
1119 if (ptr < max-1) name[ptr++] = *s;
1120 s++;
1121 }
1122 if (*s == ':') s++;
1123 name[ptr++] = ':';
1124 name[ptr] = 0;
1125 return s;
1126 }
1127
1128
1129
1130 /*************************************************
1131 * Pick out a number from a string *
1132 *************************************************/
1133
1134 /* Arguments:
1135 n points to an integer into which to put the number
1136 s points to the first digit of the number
1137
1138 Returns: a pointer to the character after the last digit
1139 */
1140 /*XXX consider expanding to int_eximarith_t. But the test for
1141 "overbig numbers" in 0002 still needs to overflow it. */
1142
1143 static uschar *
1144 read_number(int *n, uschar *s)
1145 {
1146 *n = 0;
1147 while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
1148 return s;
1149 }
1150
1151 static const uschar *
1152 read_cnumber(int *n, const uschar *s)
1153 {
1154 *n = 0;
1155 while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
1156 return s;
1157 }
1158
1159
1160
1161 /*************************************************
1162 * Extract keyed subfield from a string *
1163 *************************************************/
1164
1165 /* The yield is in dynamic store; NULL means that the key was not found.
1166
1167 Arguments:
1168 key points to the name of the key
1169 s points to the string from which to extract the subfield
1170
1171 Returns: NULL if the subfield was not found, or
1172 a pointer to the subfield's data
1173 */
1174
1175 static uschar *
1176 expand_getkeyed(uschar * key, const uschar * s)
1177 {
1178 int length = Ustrlen(key);
1179 Uskip_whitespace(&s);
1180
1181 /* Loop to search for the key */
1182
1183 while (*s)
1184 {
1185 int dkeylength;
1186 uschar * data;
1187 const uschar * dkey = s;
1188
1189 while (*s && *s != '=' && !isspace(*s)) s++;
1190 dkeylength = s - dkey;
1191 if (Uskip_whitespace(&s) == '=') while (isspace(*++s));
1192
1193 data = string_dequote(&s);
1194 if (length == dkeylength && strncmpic(key, dkey, length) == 0)
1195 return data;
1196
1197 Uskip_whitespace(&s);
1198 }
1199
1200 return NULL;
1201 }
1202
1203
1204
1205 static var_entry *
1206 find_var_ent(uschar * name)
1207 {
1208 int first = 0;
1209 int last = var_table_size;
1210
1211 while (last > first)
1212 {
1213 int middle = (first + last)/2;
1214 int c = Ustrcmp(name, var_table[middle].name);
1215
1216 if (c > 0) { first = middle + 1; continue; }
1217 if (c < 0) { last = middle; continue; }
1218 return &var_table[middle];
1219 }
1220 return NULL;
1221 }
1222
1223 /*************************************************
1224 * Extract numbered subfield from string *
1225 *************************************************/
1226
1227 /* Extracts a numbered field from a string that is divided by tokens - for
1228 example a line from /etc/passwd is divided by colon characters. First field is
1229 numbered one. Negative arguments count from the right. Zero returns the whole
1230 string. Returns NULL if there are insufficient tokens in the string
1231
1232 ***WARNING***
1233 Modifies final argument - this is a dynamically generated string, so that's OK.
1234
1235 Arguments:
1236 field number of field to be extracted,
1237 first field = 1, whole string = 0, last field = -1
1238 separators characters that are used to break string into tokens
1239 s points to the string from which to extract the subfield
1240
1241 Returns: NULL if the field was not found,
1242 a pointer to the field's data inside s (modified to add 0)
1243 */
1244
1245 static uschar *
1246 expand_gettokened (int field, uschar *separators, uschar *s)
1247 {
1248 int sep = 1;
1249 int count;
1250 uschar *ss = s;
1251 uschar *fieldtext = NULL;
1252
1253 if (field == 0) return s;
1254
1255 /* Break the line up into fields in place; for field > 0 we stop when we have
1256 done the number of fields we want. For field < 0 we continue till the end of
1257 the string, counting the number of fields. */
1258
1259 count = (field > 0)? field : INT_MAX;
1260
1261 while (count-- > 0)
1262 {
1263 size_t len;
1264
1265 /* Previous field was the last one in the string. For a positive field
1266 number, this means there are not enough fields. For a negative field number,
1267 check that there are enough, and scan back to find the one that is wanted. */
1268
1269 if (sep == 0)
1270 {
1271 if (field > 0 || (-field) > (INT_MAX - count - 1)) return NULL;
1272 if ((-field) == (INT_MAX - count - 1)) return s;
1273 while (field++ < 0)
1274 {
1275 ss--;
1276 while (ss[-1] != 0) ss--;
1277 }
1278 fieldtext = ss;
1279 break;
1280 }
1281
1282 /* Previous field was not last in the string; save its start and put a
1283 zero at its end. */
1284
1285 fieldtext = ss;
1286 len = Ustrcspn(ss, separators);
1287 sep = ss[len];
1288 ss[len] = 0;
1289 ss += len + 1;
1290 }
1291
1292 return fieldtext;
1293 }
1294
1295
1296 static uschar *
1297 expand_getlistele(int field, const uschar * list)
1298 {
1299 const uschar * tlist = list;
1300 int sep = 0;
1301 uschar dummy;
1302
1303 if (field < 0)
1304 {
1305 for (field++; string_nextinlist(&tlist, &sep, &dummy, 1); ) field++;
1306 sep = 0;
1307 }
1308 if (field == 0) return NULL;
1309 while (--field > 0 && (string_nextinlist(&list, &sep, &dummy, 1))) ;
1310 return string_nextinlist(&list, &sep, NULL, 0);
1311 }
1312
1313
1314 /* Certificate fields, by name. Worry about by-OID later */
1315 /* Names are chosen to not have common prefixes */
1316
1317 #ifndef DISABLE_TLS
1318 typedef struct
1319 {
1320 uschar * name;
1321 int namelen;
1322 uschar * (*getfn)(void * cert, uschar * mod);
1323 } certfield;
1324 static certfield certfields[] =
1325 { /* linear search; no special order */
1326 { US"version", 7, &tls_cert_version },
1327 { US"serial_number", 13, &tls_cert_serial_number },
1328 { US"subject", 7, &tls_cert_subject },
1329 { US"notbefore", 9, &tls_cert_not_before },
1330 { US"notafter", 8, &tls_cert_not_after },
1331 { US"issuer", 6, &tls_cert_issuer },
1332 { US"signature", 9, &tls_cert_signature },
1333 { US"sig_algorithm", 13, &tls_cert_signature_algorithm },
1334 { US"subj_altname", 12, &tls_cert_subject_altname },
1335 { US"ocsp_uri", 8, &tls_cert_ocsp_uri },
1336 { US"crl_uri", 7, &tls_cert_crl_uri },
1337 };
1338
1339 static uschar *
1340 expand_getcertele(uschar * field, uschar * certvar)
1341 {
1342 var_entry * vp;
1343
1344 if (!(vp = find_var_ent(certvar)))
1345 {
1346 expand_string_message =
1347 string_sprintf("no variable named \"%s\"", certvar);
1348 return NULL; /* Unknown variable name */
1349 }
1350 /* NB this stops us passing certs around in variable. Might
1351 want to do that in future */
1352 if (vp->type != vtype_cert)
1353 {
1354 expand_string_message =
1355 string_sprintf("\"%s\" is not a certificate", certvar);
1356 return NULL; /* Unknown variable name */
1357 }
1358 if (!*(void **)vp->value)
1359 return NULL;
1360
1361 if (*field >= '0' && *field <= '9')
1362 return tls_cert_ext_by_oid(*(void **)vp->value, field, 0);
1363
1364 for (certfield * cp = certfields;
1365 cp < certfields + nelem(certfields);
1366 cp++)
1367 if (Ustrncmp(cp->name, field, cp->namelen) == 0)
1368 {
1369 uschar * modifier = *(field += cp->namelen) == ','
1370 ? ++field : NULL;
1371 return (*cp->getfn)( *(void **)vp->value, modifier );
1372 }
1373
1374 expand_string_message =
1375 string_sprintf("bad field selector \"%s\" for certextract", field);
1376 return NULL;
1377 }
1378 #endif /*DISABLE_TLS*/
1379
1380 /*************************************************
1381 * Extract a substring from a string *
1382 *************************************************/
1383
1384 /* Perform the ${substr or ${length expansion operations.
1385
1386 Arguments:
1387 subject the input string
1388 value1 the offset from the start of the input string to the start of
1389 the output string; if negative, count from the right.
1390 value2 the length of the output string, or negative (-1) for unset
1391 if value1 is positive, unset means "all after"
1392 if value1 is negative, unset means "all before"
1393 len set to the length of the returned string
1394
1395 Returns: pointer to the output string, or NULL if there is an error
1396 */
1397
1398 static uschar *
1399 extract_substr(uschar *subject, int value1, int value2, int *len)
1400 {
1401 int sublen = Ustrlen(subject);
1402
1403 if (value1 < 0) /* count from right */
1404 {
1405 value1 += sublen;
1406
1407 /* If the position is before the start, skip to the start, and adjust the
1408 length. If the length ends up negative, the substring is null because nothing
1409 can precede. This falls out naturally when the length is unset, meaning "all
1410 to the left". */
1411
1412 if (value1 < 0)
1413 {
1414 value2 += value1;
1415 if (value2 < 0) value2 = 0;
1416 value1 = 0;
1417 }
1418
1419 /* Otherwise an unset length => characters before value1 */
1420
1421 else if (value2 < 0)
1422 {
1423 value2 = value1;
1424 value1 = 0;
1425 }
1426 }
1427
1428 /* For a non-negative offset, if the starting position is past the end of the
1429 string, the result will be the null string. Otherwise, an unset length means
1430 "rest"; just set it to the maximum - it will be cut down below if necessary. */
1431
1432 else
1433 {
1434 if (value1 > sublen)
1435 {
1436 value1 = sublen;
1437 value2 = 0;
1438 }
1439 else if (value2 < 0) value2 = sublen;
1440 }
1441
1442 /* Cut the length down to the maximum possible for the offset value, and get
1443 the required characters. */
1444
1445 if (value1 + value2 > sublen) value2 = sublen - value1;
1446 *len = value2;
1447 return subject + value1;
1448 }
1449
1450
1451
1452
1453 /*************************************************
1454 * Old-style hash of a string *
1455 *************************************************/
1456
1457 /* Perform the ${hash expansion operation.
1458
1459 Arguments:
1460 subject the input string (an expanded substring)
1461 value1 the length of the output string; if greater or equal to the
1462 length of the input string, the input string is returned
1463 value2 the number of hash characters to use, or 26 if negative
1464 len set to the length of the returned string
1465
1466 Returns: pointer to the output string, or NULL if there is an error
1467 */
1468
1469 static uschar *
1470 compute_hash(uschar *subject, int value1, int value2, int *len)
1471 {
1472 int sublen = Ustrlen(subject);
1473
1474 if (value2 < 0) value2 = 26;
1475 else if (value2 > Ustrlen(hashcodes))
1476 {
1477 expand_string_message =
1478 string_sprintf("hash count \"%d\" too big", value2);
1479 return NULL;
1480 }
1481
1482 /* Calculate the hash text. We know it is shorter than the original string, so
1483 can safely place it in subject[] (we know that subject is always itself an
1484 expanded substring). */
1485
1486 if (value1 < sublen)
1487 {
1488 int c;
1489 int i = 0;
1490 int j = value1;
1491 while ((c = (subject[j])) != 0)
1492 {
1493 int shift = (c + j++) & 7;
1494 subject[i] ^= (c << shift) | (c >> (8-shift));
1495 if (++i >= value1) i = 0;
1496 }
1497 for (i = 0; i < value1; i++)
1498 subject[i] = hashcodes[(subject[i]) % value2];
1499 }
1500 else value1 = sublen;
1501
1502 *len = value1;
1503 return subject;
1504 }
1505
1506
1507
1508
1509 /*************************************************
1510 * Numeric hash of a string *
1511 *************************************************/
1512
1513 /* Perform the ${nhash expansion operation. The first characters of the
1514 string are treated as most important, and get the highest prime numbers.
1515
1516 Arguments:
1517 subject the input string
1518 value1 the maximum value of the first part of the result
1519 value2 the maximum value of the second part of the result,
1520 or negative to produce only a one-part result
1521 len set to the length of the returned string
1522
1523 Returns: pointer to the output string, or NULL if there is an error.
1524 */
1525
1526 static uschar *
1527 compute_nhash (uschar *subject, int value1, int value2, int *len)
1528 {
1529 uschar *s = subject;
1530 int i = 0;
1531 unsigned long int total = 0; /* no overflow */
1532
1533 while (*s != 0)
1534 {
1535 if (i == 0) i = nelem(prime) - 1;
1536 total += prime[i--] * (unsigned int)(*s++);
1537 }
1538
1539 /* If value2 is unset, just compute one number */
1540
1541 if (value2 < 0)
1542 s = string_sprintf("%lu", total % value1);
1543
1544 /* Otherwise do a div/mod hash */
1545
1546 else
1547 {
1548 total = total % (value1 * value2);
1549 s = string_sprintf("%lu/%lu", total/value2, total % value2);
1550 }
1551
1552 *len = Ustrlen(s);
1553 return s;
1554 }
1555
1556
1557
1558
1559
1560 /*************************************************
1561 * Find the value of a header or headers *
1562 *************************************************/
1563
1564 /* Multiple instances of the same header get concatenated, and this function
1565 can also return a concatenation of all the header lines. When concatenating
1566 specific headers that contain lists of addresses, a comma is inserted between
1567 them. Otherwise we use a straight concatenation. Because some messages can have
1568 pathologically large number of lines, there is a limit on the length that is
1569 returned.
1570
1571 Arguments:
1572 name the name of the header, without the leading $header_ or $h_,
1573 or NULL if a concatenation of all headers is required
1574 newsize return the size of memory block that was obtained; may be NULL
1575 if exists_only is TRUE
1576 flags FH_EXISTS_ONLY
1577 set if called from a def: test; don't need to build a string;
1578 just return a string that is not "" and not "0" if the header
1579 exists
1580 FH_WANT_RAW
1581 set if called for $rh_ or $rheader_ items; no processing,
1582 other than concatenating, will be done on the header. Also used
1583 for $message_headers_raw.
1584 FH_WANT_LIST
1585 Double colon chars in the content, and replace newline with
1586 colon between each element when concatenating; returning a
1587 colon-sep list (elements might contain newlines)
1588 charset name of charset to translate MIME words to; used only if
1589 want_raw is false; if NULL, no translation is done (this is
1590 used for $bh_ and $bheader_)
1591
1592 Returns: NULL if the header does not exist, else a pointer to a new
1593 store block
1594 */
1595
1596 static uschar *
1597 find_header(uschar *name, int *newsize, unsigned flags, uschar *charset)
1598 {
1599 BOOL found = !name;
1600 int len = name ? Ustrlen(name) : 0;
1601 BOOL comma = FALSE;
1602 gstring * g = NULL;
1603
1604 for (header_line * h = header_list; h; h = h->next)
1605 if (h->type != htype_old && h->text) /* NULL => Received: placeholder */
1606 if (!name || (len <= h->slen && strncmpic(name, h->text, len) == 0))
1607 {
1608 uschar * s, * t;
1609 size_t inc;
1610
1611 if (flags & FH_EXISTS_ONLY)
1612 return US"1"; /* don't need actual string */
1613
1614 found = TRUE;
1615 s = h->text + len; /* text to insert */
1616 if (!(flags & FH_WANT_RAW)) /* unless wanted raw, */
1617 Uskip_whitespace(&s); /* remove leading white space */
1618 t = h->text + h->slen; /* end-point */
1619
1620 /* Unless wanted raw, remove trailing whitespace, including the
1621 newline. */
1622
1623 if (flags & FH_WANT_LIST)
1624 while (t > s && t[-1] == '\n') t--;
1625 else if (!(flags & FH_WANT_RAW))
1626 {
1627 while (t > s && isspace(t[-1])) t--;
1628
1629 /* Set comma if handling a single header and it's one of those
1630 that contains an address list, except when asked for raw headers. Only
1631 need to do this once. */
1632
1633 if (name && !comma && Ustrchr("BCFRST", h->type)) comma = TRUE;
1634 }
1635
1636 /* Trim the header roughly if we're approaching limits */
1637 inc = t - s;
1638 if (gstring_length(g) + inc > header_insert_maxlen)
1639 inc = header_insert_maxlen - gstring_length(g);
1640
1641 /* For raw just copy the data; for a list, add the data as a colon-sep
1642 list-element; for comma-list add as an unchecked comma,newline sep
1643 list-elemment; for other nonraw add as an unchecked newline-sep list (we
1644 stripped trailing WS above including the newline). We ignore the potential
1645 expansion due to colon-doubling, just leaving the loop if the limit is met
1646 or exceeded. */
1647
1648 if (flags & FH_WANT_LIST)
1649 g = string_append_listele_n(g, ':', s, (unsigned)inc);
1650 else if (flags & FH_WANT_RAW)
1651 g = string_catn(g, s, (unsigned)inc);
1652 else if (inc > 0)
1653 g = string_append2_listele_n(g, comma ? US",\n" : US"\n",
1654 s, (unsigned)inc);
1655
1656 if (gstring_length(g) >= header_insert_maxlen) break;
1657 }
1658
1659 if (!found) return NULL; /* No header found */
1660 if (!g) return US"";
1661
1662 /* That's all we do for raw header expansion. */
1663
1664 *newsize = g->size;
1665 if (flags & FH_WANT_RAW)
1666 return string_from_gstring(g);
1667
1668 /* Otherwise do RFC 2047 decoding, translating the charset if requested.
1669 The rfc2047_decode2() function can return an error with decoded data if the
1670 charset translation fails. If decoding fails, it returns NULL. */
1671
1672 else
1673 {
1674 uschar * error, * decoded = rfc2047_decode2(string_from_gstring(g),
1675 check_rfc2047_length, charset, '?', NULL, newsize, &error);
1676 if (error)
1677 DEBUG(D_any) debug_printf("*** error in RFC 2047 decoding: %s\n"
1678 " input was: %s\n", error, g->s);
1679 return decoded ? decoded : string_from_gstring(g);
1680 }
1681 }
1682
1683
1684
1685
1686 /* Append a "local" element to an Authentication-Results: header
1687 if this was a non-smtp message.
1688 */
1689
1690 static gstring *
1691 authres_local(gstring * g, const uschar * sysname)
1692 {
1693 if (!f.authentication_local)
1694 return g;
1695 g = string_append(g, 3, US";\n\tlocal=pass (non-smtp, ", sysname, US")");
1696 if (authenticated_id) g = string_append(g, 2, " u=", authenticated_id);
1697 return g;
1698 }
1699
1700
1701 /* Append an "iprev" element to an Authentication-Results: header
1702 if we have attempted to get the calling host's name.
1703 */
1704
1705 static gstring *
1706 authres_iprev(gstring * g)
1707 {
1708 if (sender_host_name)
1709 g = string_append(g, 3, US";\n\tiprev=pass (", sender_host_name, US")");
1710 else if (host_lookup_deferred)
1711 g = string_catn(g, US";\n\tiprev=temperror", 19);
1712 else if (host_lookup_failed)
1713 g = string_catn(g, US";\n\tiprev=fail", 13);
1714 else
1715 return g;
1716
1717 if (sender_host_address)
1718 g = string_append(g, 2, US" smtp.remote-ip=", sender_host_address);
1719 return g;
1720 }
1721
1722
1723
1724 /*************************************************
1725 * Return list of recipients *
1726 *************************************************/
1727 /* A recipients list is available only during system message filtering,
1728 during ACL processing after DATA, and while expanding pipe commands
1729 generated from a system filter, but not elsewhere. */
1730
1731 static uschar *
1732 fn_recipients(void)
1733 {
1734 uschar * s;
1735 gstring * g = NULL;
1736
1737 if (!f.enable_dollar_recipients) return NULL;
1738
1739 for (int i = 0; i < recipients_count; i++)
1740 {
1741 s = recipients_list[i].address;
1742 g = string_append2_listele_n(g, US", ", s, Ustrlen(s));
1743 }
1744 return g ? g->s : NULL;
1745 }
1746
1747
1748 /*************************************************
1749 * Return size of queue *
1750 *************************************************/
1751 /* Ask the daemon for the queue size */
1752
1753 static uschar *
1754 fn_queue_size(void)
1755 {
1756 struct sockaddr_un sa_un = {.sun_family = AF_UNIX};
1757 uschar buf[16];
1758 int fd;
1759 ssize_t len;
1760 const uschar * where;
1761 #ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1762 uschar * sname;
1763 #endif
1764 fd_set fds;
1765 struct timeval tv;
1766
1767 if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
1768 {
1769 DEBUG(D_expand) debug_printf(" socket: %s\n", strerror(errno));
1770 return NULL;
1771 }
1772
1773 #ifdef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1774 sa_un.sun_path[0] = 0; /* Abstract local socket addr - Linux-specific? */
1775 len = offsetof(struct sockaddr_un, sun_path) + 1
1776 + snprintf(sa_un.sun_path+1, sizeof(sa_un.sun_path)-1, "exim_%d", getpid());
1777 #else
1778 sname = string_sprintf("%s/p_%d", spool_directory, getpid());
1779 len = offsetof(struct sockaddr_un, sun_path)
1780 + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path), "%s", sname);
1781 #endif
1782
1783 if (bind(fd, (const struct sockaddr *)&sa_un, len) < 0)
1784 { where = US"bind"; goto bad; }
1785
1786 #ifdef notdef
1787 debug_printf("local addr '%s%s'\n",
1788 *sa_un.sun_path ? "" : "@",
1789 sa_un.sun_path + (*sa_un.sun_path ? 0 : 1));
1790 #endif
1791
1792 #ifdef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1793 sa_un.sun_path[0] = 0; /* Abstract local socket addr - Linux-specific? */
1794 len = offsetof(struct sockaddr_un, sun_path) + 1
1795 + snprintf(sa_un.sun_path+1, sizeof(sa_un.sun_path)-1, "%s",
1796 expand_string(notifier_socket));
1797 #else
1798 len = offsetof(struct sockaddr_un, sun_path)
1799 + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path), "%s",
1800 expand_string(notifier_socket));
1801 #endif
1802
1803 if (connect(fd, (const struct sockaddr *)&sa_un, len) < 0)
1804 { where = US"connect"; goto bad2; }
1805
1806 buf[0] = NOTIFY_QUEUE_SIZE_REQ;
1807 if (send(fd, buf, 1, 0) < 0) { where = US"send"; goto bad; }
1808
1809 FD_ZERO(&fds); FD_SET(fd, &fds);
1810 tv.tv_sec = 2; tv.tv_usec = 0;
1811 if (select(fd + 1, (SELECT_ARG2_TYPE *)&fds, NULL, NULL, &tv) != 1)
1812 {
1813 DEBUG(D_expand) debug_printf("no daemon response; using local evaluation\n");
1814 len = snprintf(CS buf, sizeof(buf), "%u", queue_count_cached());
1815 }
1816 else if ((len = recv(fd, buf, sizeof(buf), 0)) < 0)
1817 { where = US"recv"; goto bad2; }
1818
1819 close(fd);
1820 #ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1821 Uunlink(sname);
1822 #endif
1823 return string_copyn(buf, len);
1824
1825 bad2:
1826 #ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
1827 Uunlink(sname);
1828 #endif
1829 bad:
1830 close(fd);
1831 DEBUG(D_expand) debug_printf(" %s: %s\n", where, strerror(errno));
1832 return NULL;
1833 }
1834
1835
1836 /*************************************************
1837 * Find value of a variable *
1838 *************************************************/
1839
1840 /* The table of variables is kept in alphabetic order, so we can search it
1841 using a binary chop. The "choplen" variable is nothing to do with the binary
1842 chop.
1843
1844 Arguments:
1845 name the name of the variable being sought
1846 exists_only TRUE if this is a def: test; passed on to find_header()
1847 skipping TRUE => skip any processing evaluation; this is not the same as
1848 exists_only because def: may test for values that are first
1849 evaluated here
1850 newsize pointer to an int which is initially zero; if the answer is in
1851 a new memory buffer, *newsize is set to its size
1852
1853 Returns: NULL if the variable does not exist, or
1854 a pointer to the variable's contents, or
1855 something non-NULL if exists_only is TRUE
1856 */
1857
1858 static uschar *
1859 find_variable(uschar *name, BOOL exists_only, BOOL skipping, int *newsize)
1860 {
1861 var_entry * vp;
1862 uschar *s, *domain;
1863 uschar **ss;
1864 void * val;
1865
1866 /* Handle ACL variables, whose names are of the form acl_cxxx or acl_mxxx.
1867 Originally, xxx had to be a number in the range 0-9 (later 0-19), but from
1868 release 4.64 onwards arbitrary names are permitted, as long as the first 5
1869 characters are acl_c or acl_m and the sixth is either a digit or an underscore
1870 (this gave backwards compatibility at the changeover). There may be built-in
1871 variables whose names start acl_ but they should never start in this way. This
1872 slightly messy specification is a consequence of the history, needless to say.
1873
1874 If an ACL variable does not exist, treat it as empty, unless strict_acl_vars is
1875 set, in which case give an error. */
1876
1877 if ((Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) &&
1878 !isalpha(name[5]))
1879 {
1880 tree_node * node =
1881 tree_search(name[4] == 'c' ? acl_var_c : acl_var_m, name + 4);
1882 return node ? node->data.ptr : strict_acl_vars ? NULL : US"";
1883 }
1884 else if (Ustrncmp(name, "r_", 2) == 0)
1885 {
1886 tree_node * node = tree_search(router_var, name + 2);
1887 return node ? node->data.ptr : strict_acl_vars ? NULL : US"";
1888 }
1889
1890 /* Handle $auth<n> variables. */
1891
1892 if (Ustrncmp(name, "auth", 4) == 0)
1893 {
1894 uschar *endptr;
1895 int n = Ustrtoul(name + 4, &endptr, 10);
1896 if (*endptr == 0 && n != 0 && n <= AUTH_VARS)
1897 return !auth_vars[n-1] ? US"" : auth_vars[n-1];
1898 }
1899 else if (Ustrncmp(name, "regex", 5) == 0)
1900 {
1901 uschar *endptr;
1902 int n = Ustrtoul(name + 5, &endptr, 10);
1903 if (*endptr == 0 && n != 0 && n <= REGEX_VARS)
1904 return !regex_vars[n-1] ? US"" : regex_vars[n-1];
1905 }
1906
1907 /* For all other variables, search the table */
1908
1909 if (!(vp = find_var_ent(name)))
1910 return NULL; /* Unknown variable name */
1911
1912 /* Found an existing variable. If in skipping state, the value isn't needed,
1913 and we want to avoid processing (such as looking up the host name). */
1914
1915 if (skipping)
1916 return US"";
1917
1918 val = vp->value;
1919 switch (vp->type)
1920 {
1921 case vtype_filter_int:
1922 if (!f.filter_running) return NULL;
1923 /* Fall through */
1924 /* VVVVVVVVVVVV */
1925 case vtype_int:
1926 sprintf(CS var_buffer, "%d", *(int *)(val)); /* Integer */
1927 return var_buffer;
1928
1929 case vtype_ino:
1930 sprintf(CS var_buffer, "%ld", (long int)(*(ino_t *)(val))); /* Inode */
1931 return var_buffer;
1932
1933 case vtype_gid:
1934 sprintf(CS var_buffer, "%ld", (long int)(*(gid_t *)(val))); /* gid */
1935 return var_buffer;
1936
1937 case vtype_uid:
1938 sprintf(CS var_buffer, "%ld", (long int)(*(uid_t *)(val))); /* uid */
1939 return var_buffer;
1940
1941 case vtype_bool:
1942 sprintf(CS var_buffer, "%s", *(BOOL *)(val) ? "yes" : "no"); /* bool */
1943 return var_buffer;
1944
1945 case vtype_stringptr: /* Pointer to string */
1946 return (s = *((uschar **)(val))) ? s : US"";
1947
1948 case vtype_pid:
1949 sprintf(CS var_buffer, "%d", (int)getpid()); /* pid */
1950 return var_buffer;
1951
1952 case vtype_load_avg:
1953 sprintf(CS var_buffer, "%d", OS_GETLOADAVG()); /* load_average */
1954 return var_buffer;
1955
1956 case vtype_host_lookup: /* Lookup if not done so */
1957 if ( !sender_host_name && sender_host_address
1958 && !host_lookup_failed && host_name_lookup() == OK)
1959 host_build_sender_fullhost();
1960 return sender_host_name ? sender_host_name : US"";
1961
1962 case vtype_localpart: /* Get local part from address */
1963 if (!(s = *((uschar **)(val)))) return US"";
1964 if (!(domain = Ustrrchr(s, '@'))) return s;
1965 if (domain - s > sizeof(var_buffer) - 1)
1966 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than " SIZE_T_FMT
1967 " in string expansion", sizeof(var_buffer));
1968 return string_copyn(s, domain - s);
1969
1970 case vtype_domain: /* Get domain from address */
1971 if (!(s = *((uschar **)(val)))) return US"";
1972 domain = Ustrrchr(s, '@');
1973 return domain ? domain + 1 : US"";
1974
1975 case vtype_msgheaders:
1976 return find_header(NULL, newsize, exists_only ? FH_EXISTS_ONLY : 0, NULL);
1977
1978 case vtype_msgheaders_raw:
1979 return find_header(NULL, newsize,
1980 exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW, NULL);
1981
1982 case vtype_msgbody: /* Pointer to msgbody string */
1983 case vtype_msgbody_end: /* Ditto, the end of the msg */
1984 ss = (uschar **)(val);
1985 if (!*ss && deliver_datafile >= 0) /* Read body when needed */
1986 {
1987 uschar *body;
1988 off_t start_offset = SPOOL_DATA_START_OFFSET;
1989 int len = message_body_visible;
1990 if (len > message_size) len = message_size;
1991 *ss = body = store_malloc(len+1);
1992 body[0] = 0;
1993 if (vp->type == vtype_msgbody_end)
1994 {
1995 struct stat statbuf;
1996 if (fstat(deliver_datafile, &statbuf) == 0)
1997 {
1998 start_offset = statbuf.st_size - len;
1999 if (start_offset < SPOOL_DATA_START_OFFSET)
2000 start_offset = SPOOL_DATA_START_OFFSET;
2001 }
2002 }
2003 if (lseek(deliver_datafile, start_offset, SEEK_SET) < 0)
2004 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "deliver_datafile lseek: %s",
2005 strerror(errno));
2006 len = read(deliver_datafile, body, len);
2007 if (len > 0)
2008 {
2009 body[len] = 0;
2010 if (message_body_newlines) /* Separate loops for efficiency */
2011 while (len > 0)
2012 { if (body[--len] == 0) body[len] = ' '; }
2013 else
2014 while (len > 0)
2015 { if (body[--len] == '\n' || body[len] == 0) body[len] = ' '; }
2016 }
2017 }
2018 return *ss ? *ss : US"";
2019
2020 case vtype_todbsdin: /* BSD inbox time of day */
2021 return tod_stamp(tod_bsdin);
2022
2023 case vtype_tode: /* Unix epoch time of day */
2024 return tod_stamp(tod_epoch);
2025
2026 case vtype_todel: /* Unix epoch/usec time of day */
2027 return tod_stamp(tod_epoch_l);
2028
2029 case vtype_todf: /* Full time of day */
2030 return tod_stamp(tod_full);
2031
2032 case vtype_todl: /* Log format time of day */
2033 return tod_stamp(tod_log_bare); /* (without timezone) */
2034
2035 case vtype_todzone: /* Time zone offset only */
2036 return tod_stamp(tod_zone);
2037
2038 case vtype_todzulu: /* Zulu time */
2039 return tod_stamp(tod_zulu);
2040
2041 case vtype_todlf: /* Log file datestamp tod */
2042 return tod_stamp(tod_log_datestamp_daily);
2043
2044 case vtype_reply: /* Get reply address */
2045 s = find_header(US"reply-to:", newsize,
2046 exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW,
2047 headers_charset);
2048 if (s) Uskip_whitespace(&s);
2049 if (!s || !*s)
2050 {
2051 *newsize = 0; /* For the *s==0 case */
2052 s = find_header(US"from:", newsize,
2053 exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW,
2054 headers_charset);
2055 }
2056 if (s)
2057 {
2058 uschar *t;
2059 Uskip_whitespace(&s);
2060 for (t = s; *t; t++) if (*t == '\n') *t = ' ';
2061 while (t > s && isspace(t[-1])) t--;
2062 *t = 0;
2063 }
2064 return s ? s : US"";
2065
2066 case vtype_string_func:
2067 {
2068 stringptr_fn_t * fn = (stringptr_fn_t *) val;
2069 return fn();
2070 }
2071
2072 case vtype_pspace:
2073 {
2074 int inodes;
2075 sprintf(CS var_buffer, PR_EXIM_ARITH,
2076 receive_statvfs(val == (void *)TRUE, &inodes));
2077 }
2078 return var_buffer;
2079
2080 case vtype_pinodes:
2081 {
2082 int inodes;
2083 (void) receive_statvfs(val == (void *)TRUE, &inodes);
2084 sprintf(CS var_buffer, "%d", inodes);
2085 }
2086 return var_buffer;
2087
2088 case vtype_cert:
2089 return *(void **)val ? US"<cert>" : US"";
2090
2091 #ifndef DISABLE_DKIM
2092 case vtype_dkim:
2093 return dkim_exim_expand_query((int)(long)val);
2094 #endif
2095
2096 }
2097
2098 return NULL; /* Unknown variable. Silences static checkers. */
2099 }
2100
2101
2102
2103
2104 void
2105 modify_variable(uschar *name, void * value)
2106 {
2107 var_entry * vp;
2108 if ((vp = find_var_ent(name))) vp->value = value;
2109 return; /* Unknown variable name, fail silently */
2110 }
2111
2112
2113
2114
2115
2116
2117 /*************************************************
2118 * Read and expand substrings *
2119 *************************************************/
2120
2121 /* This function is called to read and expand argument substrings for various
2122 expansion items. Some have a minimum requirement that is less than the maximum;
2123 in these cases, the first non-present one is set to NULL.
2124
2125 Arguments:
2126 sub points to vector of pointers to set
2127 n maximum number of substrings
2128 m minimum required
2129 sptr points to current string pointer
2130 skipping the skipping flag
2131 check_end if TRUE, check for final '}'
2132 name name of item, for error message
2133 resetok if not NULL, pointer to flag - write FALSE if unsafe to reset
2134 the store.
2135
2136 Returns: 0 OK; string pointer updated
2137 1 curly bracketing error (too few arguments)
2138 2 too many arguments (only if check_end is set); message set
2139 3 other error (expansion failure)
2140 */
2141
2142 static int
2143 read_subs(uschar **sub, int n, int m, const uschar **sptr, BOOL skipping,
2144 BOOL check_end, uschar *name, BOOL *resetok)
2145 {
2146 const uschar *s = *sptr;
2147
2148 Uskip_whitespace(&s);
2149 for (int i = 0; i < n; i++)
2150 {
2151 if (*s != '{')
2152 {
2153 if (i < m)
2154 {
2155 expand_string_message = string_sprintf("Not enough arguments for '%s' "
2156 "(min is %d)", name, m);
2157 return 1;
2158 }
2159 sub[i] = NULL;
2160 break;
2161 }
2162 if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, skipping, TRUE, resetok)))
2163 return 3;
2164 if (*s++ != '}') return 1;
2165 Uskip_whitespace(&s);
2166 }
2167 if (check_end && *s++ != '}')
2168 {
2169 if (s[-1] == '{')
2170 {
2171 expand_string_message = string_sprintf("Too many arguments for '%s' "
2172 "(max is %d)", name, n);
2173 return 2;
2174 }
2175 expand_string_message = string_sprintf("missing '}' after '%s'", name);
2176 return 1;
2177 }
2178
2179 *sptr = s;
2180 return 0;
2181 }
2182
2183
2184
2185
2186 /*************************************************
2187 * Elaborate message for bad variable *
2188 *************************************************/
2189
2190 /* For the "unknown variable" message, take a look at the variable's name, and
2191 give additional information about possible ACL variables. The extra information
2192 is added on to expand_string_message.
2193
2194 Argument: the name of the variable
2195 Returns: nothing
2196 */
2197
2198 static void
2199 check_variable_error_message(uschar *name)
2200 {
2201 if (Ustrncmp(name, "acl_", 4) == 0)
2202 expand_string_message = string_sprintf("%s (%s)", expand_string_message,
2203 (name[4] == 'c' || name[4] == 'm')?
2204 (isalpha(name[5])?
2205 US"6th character of a user-defined ACL variable must be a digit or underscore" :
2206 US"strict_acl_vars is set" /* Syntax is OK, it has to be this */
2207 ) :
2208 US"user-defined ACL variables must start acl_c or acl_m");
2209 }
2210
2211
2212
2213 /*
2214 Load args from sub array to globals, and call acl_check().
2215 Sub array will be corrupted on return.
2216
2217 Returns: OK access is granted by an ACCEPT verb
2218 DISCARD access is (apparently) granted by a DISCARD verb
2219 FAIL access is denied
2220 FAIL_DROP access is denied; drop the connection
2221 DEFER can't tell at the moment
2222 ERROR disaster
2223 */
2224 static int
2225 eval_acl(uschar ** sub, int nsub, uschar ** user_msgp)
2226 {
2227 int i;
2228 int sav_narg = acl_narg;
2229 int ret;
2230 uschar * dummy_logmsg;
2231 extern int acl_where;
2232
2233 if(--nsub > nelem(acl_arg)) nsub = nelem(acl_arg);
2234 for (i = 0; i < nsub && sub[i+1]; i++)
2235 {
2236 uschar * tmp = acl_arg[i];
2237 acl_arg[i] = sub[i+1]; /* place callers args in the globals */
2238 sub[i+1] = tmp; /* stash the old args using our caller's storage */
2239 }
2240 acl_narg = i;
2241 while (i < nsub)
2242 {
2243 sub[i+1] = acl_arg[i];
2244 acl_arg[i++] = NULL;
2245 }
2246
2247 DEBUG(D_expand)
2248 debug_printf_indent("expanding: acl: %s arg: %s%s\n",
2249 sub[0],
2250 acl_narg>0 ? acl_arg[0] : US"<none>",
2251 acl_narg>1 ? " +more" : "");
2252
2253 ret = acl_eval(acl_where, sub[0], user_msgp, &dummy_logmsg);
2254
2255 for (i = 0; i < nsub; i++)
2256 acl_arg[i] = sub[i+1]; /* restore old args */
2257 acl_narg = sav_narg;
2258
2259 return ret;
2260 }
2261
2262
2263
2264
2265 /* Return pointer to dewrapped string, with enclosing specified chars removed.
2266 The given string is modified on return. Leading whitespace is skipped while
2267 looking for the opening wrap character, then the rest is scanned for the trailing
2268 (non-escaped) wrap character. A backslash in the string will act as an escape.
2269
2270 A nul is written over the trailing wrap, and a pointer to the char after the
2271 leading wrap is returned.
2272
2273 Arguments:
2274 s String for de-wrapping
2275 wrap Two-char string, the first being the opener, second the closer wrapping
2276 character
2277 Return:
2278 Pointer to de-wrapped string, or NULL on error (with expand_string_message set).
2279 */
2280
2281 static uschar *
2282 dewrap(uschar * s, const uschar * wrap)
2283 {
2284 uschar * p = s;
2285 unsigned depth = 0;
2286 BOOL quotesmode = wrap[0] == wrap[1];
2287
2288 if (Uskip_whitespace(&p) == *wrap)
2289 {
2290 s = ++p;
2291 wrap++;
2292 while (*p)
2293 {
2294 if (*p == '\\') p++;
2295 else if (!quotesmode && *p == wrap[-1]) depth++;
2296 else if (*p == *wrap)
2297 if (depth == 0)
2298 {
2299 *p = '\0';
2300 return s;
2301 }
2302 else
2303 depth--;
2304 p++;
2305 }
2306 }
2307 expand_string_message = string_sprintf("missing '%c'", *wrap);
2308 return NULL;
2309 }
2310
2311
2312 /* Pull off the leading array or object element, returning
2313 a copy in an allocated string. Update the list pointer.
2314
2315 The element may itself be an abject or array.
2316 Return NULL when the list is empty.
2317 */
2318
2319 static uschar *
2320 json_nextinlist(const uschar ** list)
2321 {
2322 unsigned array_depth = 0, object_depth = 0;
2323 const uschar * s = *list, * item;
2324
2325 skip_whitespace(&s);
2326
2327 for (item = s;
2328 *s && (*s != ',' || array_depth != 0 || object_depth != 0);
2329 s++)
2330 switch (*s)
2331 {
2332 case '[': array_depth++; break;
2333 case ']': array_depth--; break;
2334 case '{': object_depth++; break;
2335 case '}': object_depth--; break;
2336 }
2337 *list = *s ? s+1 : s;
2338 if (item == s) return NULL;
2339 item = string_copyn(item, s - item);
2340 DEBUG(D_expand) debug_printf_indent(" json ele: '%s'\n", item);
2341 return US item;
2342 }
2343
2344
2345
2346 /************************************************/
2347 /* Return offset in ops table, or -1 if not found.
2348 Repoint to just after the operator in the string.
2349
2350 Argument:
2351 ss string representation of operator
2352 opname split-out operator name
2353 */
2354
2355 static int
2356 identify_operator(const uschar ** ss, uschar ** opname)
2357 {
2358 const uschar * s = *ss;
2359 uschar name[256];
2360
2361 /* Numeric comparisons are symbolic */
2362
2363 if (*s == '=' || *s == '>' || *s == '<')
2364 {
2365 int p = 0;
2366 name[p++] = *s++;
2367 if (*s == '=')
2368 {
2369 name[p++] = '=';
2370 s++;
2371 }
2372 name[p] = 0;
2373 }
2374
2375 /* All other conditions are named */
2376
2377 else
2378 s = read_name(name, sizeof(name), s, US"_");
2379 *ss = s;
2380
2381 /* If we haven't read a name, it means some non-alpha character is first. */
2382
2383 if (!name[0])
2384 {
2385 expand_string_message = string_sprintf("condition name expected, "
2386 "but found \"%.16s\"", s);
2387 return -1;
2388 }
2389 if (opname)
2390 *opname = string_copy(name);
2391
2392 return chop_match(name, cond_table, nelem(cond_table));
2393 }
2394
2395
2396 /*************************************************
2397 * Handle MD5 or SHA-1 computation for HMAC *
2398 *************************************************/
2399
2400 /* These are some wrapping functions that enable the HMAC code to be a bit
2401 cleaner. A good compiler will spot the tail recursion.
2402
2403 Arguments:
2404 type HMAC_MD5 or HMAC_SHA1
2405 remaining are as for the cryptographic hash functions
2406
2407 Returns: nothing
2408 */
2409
2410 static void
2411 chash_start(int type, void * base)
2412 {
2413 if (type == HMAC_MD5)
2414 md5_start((md5 *)base);
2415 else
2416 sha1_start((hctx *)base);
2417 }
2418
2419 static void
2420 chash_mid(int type, void * base, const uschar * string)
2421 {
2422 if (type == HMAC_MD5)
2423 md5_mid((md5 *)base, string);
2424 else
2425 sha1_mid((hctx *)base, string);
2426 }
2427
2428 static void
2429 chash_end(int type, void * base, const uschar * string, int length,
2430 uschar * digest)
2431 {
2432 if (type == HMAC_MD5)
2433 md5_end((md5 *)base, string, length, digest);
2434 else
2435 sha1_end((hctx *)base, string, length, digest);
2436 }
2437
2438
2439
2440
2441 /* Do an hmac_md5. The result is _not_ nul-terminated, and is sized as
2442 the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
2443
2444 Arguments:
2445 key encoding key, nul-terminated
2446 src data to be hashed, nul-terminated
2447 buf output buffer
2448 len size of output buffer
2449 */
2450
2451 static void
2452 hmac_md5(const uschar * key, const uschar * src, uschar * buf, unsigned len)
2453 {
2454 md5 md5_base;
2455 const uschar * keyptr;
2456 uschar * p;
2457 unsigned int keylen;
2458
2459 #define MD5_HASHLEN 16
2460 #define MD5_HASHBLOCKLEN 64
2461
2462 uschar keyhash[MD5_HASHLEN];
2463 uschar innerhash[MD5_HASHLEN];
2464 uschar finalhash[MD5_HASHLEN];
2465 uschar innerkey[MD5_HASHBLOCKLEN];
2466 uschar outerkey[MD5_HASHBLOCKLEN];
2467
2468 keyptr = key;
2469 keylen = Ustrlen(keyptr);
2470
2471 /* If the key is longer than the hash block length, then hash the key
2472 first */
2473
2474 if (keylen > MD5_HASHBLOCKLEN)
2475 {
2476 chash_start(HMAC_MD5, &md5_base);
2477 chash_end(HMAC_MD5, &md5_base, keyptr, keylen, keyhash);
2478 keyptr = keyhash;
2479 keylen = MD5_HASHLEN;
2480 }
2481
2482 /* Now make the inner and outer key values */
2483
2484 memset(innerkey, 0x36, MD5_HASHBLOCKLEN);
2485 memset(outerkey, 0x5c, MD5_HASHBLOCKLEN);
2486
2487 for (int i = 0; i < keylen; i++)
2488 {
2489 innerkey[i] ^= keyptr[i];
2490 outerkey[i] ^= keyptr[i];
2491 }
2492
2493 /* Now do the hashes */
2494
2495 chash_start(HMAC_MD5, &md5_base);
2496 chash_mid(HMAC_MD5, &md5_base, innerkey);
2497 chash_end(HMAC_MD5, &md5_base, src, Ustrlen(src), innerhash);
2498
2499 chash_start(HMAC_MD5, &md5_base);
2500 chash_mid(HMAC_MD5, &md5_base, outerkey);
2501 chash_end(HMAC_MD5, &md5_base, innerhash, MD5_HASHLEN, finalhash);
2502
2503 /* Encode the final hash as a hex string, limited by output buffer size */
2504
2505 p = buf;
2506 for (int i = 0, j = len; i < MD5_HASHLEN; i++)
2507 {
2508 if (j-- <= 0) break;
2509 *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
2510 if (j-- <= 0) break;
2511 *p++ = hex_digits[finalhash[i] & 0x0f];
2512 }
2513 return;
2514 }
2515
2516
2517 /*************************************************
2518 * Read and evaluate a condition *
2519 *************************************************/
2520
2521 /*
2522 Arguments:
2523 s points to the start of the condition text
2524 resetok points to a BOOL which is written false if it is unsafe to
2525 free memory. Certain condition types (acl) may have side-effect
2526 allocation which must be preserved.
2527 yield points to a BOOL to hold the result of the condition test;
2528 if NULL, we are just reading through a condition that is
2529 part of an "or" combination to check syntax, or in a state
2530 where the answer isn't required
2531
2532 Returns: a pointer to the first character after the condition, or
2533 NULL after an error
2534 */
2535
2536 static const uschar *
2537 eval_condition(const uschar *s, BOOL *resetok, BOOL *yield)
2538 {
2539 BOOL testfor = TRUE;
2540 BOOL tempcond, combined_cond;
2541 BOOL *subcondptr;
2542 BOOL sub2_honour_dollar = TRUE;
2543 BOOL is_forany, is_json, is_jsons;
2544 int rc, cond_type, roffset;
2545 int_eximarith_t num[2];
2546 struct stat statbuf;
2547 uschar * opname;
2548 uschar name[256];
2549 const uschar *sub[10];
2550
2551 const pcre *re;
2552 const uschar *rerror;
2553
2554 for (;;)
2555 if (Uskip_whitespace(&s) == '!') { testfor = !testfor; s++; } else break;
2556
2557 switch(cond_type = identify_operator(&s, &opname))
2558 {
2559 /* def: tests for a non-empty variable, or for the existence of a header. If
2560 yield == NULL we are in a skipping state, and don't care about the answer. */
2561
2562 case ECOND_DEF:
2563 {
2564 uschar * t;
2565
2566 if (*s != ':')
2567 {
2568 expand_string_message = US"\":\" expected after \"def\"";
2569 return NULL;
2570 }
2571
2572 s = read_name(name, sizeof(name), s+1, US"_");
2573
2574 /* Test for a header's existence. If the name contains a closing brace
2575 character, this may be a user error where the terminating colon has been
2576 omitted. Set a flag to adjust a subsequent error message in this case. */
2577
2578 if ( ( *(t = name) == 'h'
2579 || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
2580 )
2581 && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
2582 )
2583 {
2584 s = read_header_name(name, sizeof(name), s);
2585 /* {-for-text-editors */
2586 if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
2587 if (yield) *yield =
2588 (find_header(name, NULL, FH_EXISTS_ONLY, NULL) != NULL) == testfor;
2589 }
2590
2591 /* Test for a variable's having a non-empty value. A non-existent variable
2592 causes an expansion failure. */
2593
2594 else
2595 {
2596 if (!(t = find_variable(name, TRUE, yield == NULL, NULL)))
2597 {
2598 expand_string_message = name[0]
2599 ? string_sprintf("unknown variable \"%s\" after \"def:\"", name)
2600 : US"variable name omitted after \"def:\"";
2601 check_variable_error_message(name);
2602 return NULL;
2603 }
2604 if (yield) *yield = (t[0] != 0) == testfor;
2605 }
2606
2607 return s;
2608 }
2609
2610
2611 /* first_delivery tests for first delivery attempt */
2612
2613 case ECOND_FIRST_DELIVERY:
2614 if (yield) *yield = f.deliver_firsttime == testfor;
2615 return s;
2616
2617
2618 /* queue_running tests for any process started by a queue runner */
2619
2620 case ECOND_QUEUE_RUNNING:
2621 if (yield) *yield = (queue_run_pid != (pid_t)0) == testfor;
2622 return s;
2623
2624
2625 /* exists: tests for file existence
2626 isip: tests for any IP address
2627 isip4: tests for an IPv4 address
2628 isip6: tests for an IPv6 address
2629 pam: does PAM authentication
2630 radius: does RADIUS authentication
2631 ldapauth: does LDAP authentication
2632 pwcheck: does Cyrus SASL pwcheck authentication
2633 */
2634
2635 case ECOND_EXISTS:
2636 case ECOND_ISIP:
2637 case ECOND_ISIP4:
2638 case ECOND_ISIP6:
2639 case ECOND_PAM:
2640 case ECOND_RADIUS:
2641 case ECOND_LDAPAUTH:
2642 case ECOND_PWCHECK:
2643
2644 if (Uskip_whitespace(&s) != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2645
2646 sub[0] = expand_string_internal(s+1, TRUE, &s, yield == NULL, TRUE, resetok);
2647 if (!sub[0]) return NULL;
2648 /* {-for-text-editors */
2649 if (*s++ != '}') goto COND_FAILED_CURLY_END;
2650
2651 if (!yield) return s; /* No need to run the test if skipping */
2652
2653 switch(cond_type)
2654 {
2655 case ECOND_EXISTS:
2656 if ((expand_forbid & RDO_EXISTS) != 0)
2657 {
2658 expand_string_message = US"File existence tests are not permitted";
2659 return NULL;
2660 }
2661 *yield = (Ustat(sub[0], &statbuf) == 0) == testfor;
2662 break;
2663
2664 case ECOND_ISIP:
2665 case ECOND_ISIP4:
2666 case ECOND_ISIP6:
2667 rc = string_is_ip_address(sub[0], NULL);
2668 *yield = ((cond_type == ECOND_ISIP)? (rc != 0) :
2669 (cond_type == ECOND_ISIP4)? (rc == 4) : (rc == 6)) == testfor;
2670 break;
2671
2672 /* Various authentication tests - all optionally compiled */
2673
2674 case ECOND_PAM:
2675 #ifdef SUPPORT_PAM
2676 rc = auth_call_pam(sub[0], &expand_string_message);
2677 goto END_AUTH;
2678 #else
2679 goto COND_FAILED_NOT_COMPILED;
2680 #endif /* SUPPORT_PAM */
2681
2682 case ECOND_RADIUS:
2683 #ifdef RADIUS_CONFIG_FILE
2684 rc = auth_call_radius(sub[0], &expand_string_message);
2685 goto END_AUTH;
2686 #else
2687 goto COND_FAILED_NOT_COMPILED;
2688 #endif /* RADIUS_CONFIG_FILE */
2689
2690 case ECOND_LDAPAUTH:
2691 #ifdef LOOKUP_LDAP
2692 {
2693 /* Just to keep the interface the same */
2694 BOOL do_cache;
2695 int old_pool = store_pool;
2696 store_pool = POOL_SEARCH;
2697 rc = eldapauth_find((void *)(-1), NULL, sub[0], Ustrlen(sub[0]), NULL,
2698 &expand_string_message, &do_cache);
2699 store_pool = old_pool;
2700 }
2701 goto END_AUTH;
2702 #else
2703 goto COND_FAILED_NOT_COMPILED;
2704 #endif /* LOOKUP_LDAP */
2705
2706 case ECOND_PWCHECK:
2707 #ifdef CYRUS_PWCHECK_SOCKET
2708 rc = auth_call_pwcheck(sub[0], &expand_string_message);
2709 goto END_AUTH;
2710 #else
2711 goto COND_FAILED_NOT_COMPILED;
2712 #endif /* CYRUS_PWCHECK_SOCKET */
2713
2714 #if defined(SUPPORT_PAM) || defined(RADIUS_CONFIG_FILE) || \
2715 defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET)
2716 END_AUTH:
2717 if (rc == ERROR || rc == DEFER) return NULL;
2718 *yield = (rc == OK) == testfor;
2719 #endif
2720 }
2721 return s;
2722
2723
2724 /* call ACL (in a conditional context). Accept true, deny false.
2725 Defer is a forced-fail. Anything set by message= goes to $value.
2726 Up to ten parameters are used; we use the braces round the name+args
2727 like the saslauthd condition does, to permit a variable number of args.
2728 See also the expansion-item version EITEM_ACL and the traditional
2729 acl modifier ACLC_ACL.
2730 Since the ACL may allocate new global variables, tell our caller to not
2731 reclaim memory.
2732 */
2733
2734 case ECOND_ACL:
2735 /* ${if acl {{name}{arg1}{arg2}...} {yes}{no}} */
2736 {
2737 uschar *sub[10];
2738 uschar *user_msg;
2739 BOOL cond = FALSE;
2740
2741 Uskip_whitespace(&s);
2742 if (*s++ != '{') goto COND_FAILED_CURLY_START; /*}*/
2743
2744 switch(read_subs(sub, nelem(sub), 1,
2745 &s, yield == NULL, TRUE, name, resetok))
2746 {
2747 case 1: expand_string_message = US"too few arguments or bracketing "
2748 "error for acl";
2749 case 2:
2750 case 3: return NULL;
2751 }
2752
2753 if (yield)
2754 {
2755 int rc;
2756 *resetok = FALSE; /* eval_acl() might allocate; do not reclaim */
2757 switch(rc = eval_acl(sub, nelem(sub), &user_msg))
2758 {
2759 case OK:
2760 cond = TRUE;
2761 case FAIL:
2762 lookup_value = NULL;
2763 if (user_msg)
2764 lookup_value = string_copy(user_msg);
2765 *yield = cond == testfor;
2766 break;
2767
2768 case DEFER:
2769 f.expand_string_forcedfail = TRUE;
2770 /*FALLTHROUGH*/
2771 default:
2772 expand_string_message = string_sprintf("%s from acl \"%s\"",
2773 rc_names[rc], sub[0]);
2774 return NULL;
2775 }
2776 }
2777 return s;
2778 }
2779
2780
2781 /* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
2782
2783 ${if saslauthd {{username}{password}{service}{realm}} {yes}{no}}
2784
2785 However, the last two are optional. That is why the whole set is enclosed
2786 in their own set of braces. */
2787
2788 case ECOND_SASLAUTHD:
2789 #ifndef CYRUS_SASLAUTHD_SOCKET
2790 goto COND_FAILED_NOT_COMPILED;
2791 #else
2792 {
2793 uschar *sub[4];
2794 Uskip_whitespace(&s);
2795 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2796 switch(read_subs(sub, nelem(sub), 2, &s, yield == NULL, TRUE, name,
2797 resetok))
2798 {
2799 case 1: expand_string_message = US"too few arguments or bracketing "
2800 "error for saslauthd";
2801 case 2:
2802 case 3: return NULL;
2803 }
2804 if (!sub[2]) sub[3] = NULL; /* realm if no service */
2805 if (yield)
2806 {
2807 int rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
2808 &expand_string_message);
2809 if (rc == ERROR || rc == DEFER) return NULL;
2810 *yield = (rc == OK) == testfor;
2811 }
2812 return s;
2813 }
2814 #endif /* CYRUS_SASLAUTHD_SOCKET */
2815
2816
2817 /* symbolic operators for numeric and string comparison, and a number of
2818 other operators, all requiring two arguments.
2819
2820 crypteq: encrypts plaintext and compares against an encrypted text,
2821 using crypt(), crypt16(), MD5 or SHA-1
2822 inlist/inlisti: checks if first argument is in the list of the second
2823 match: does a regular expression match and sets up the numerical
2824 variables if it succeeds
2825 match_address: matches in an address list
2826 match_domain: matches in a domain list
2827 match_ip: matches a host list that is restricted to IP addresses
2828 match_local_part: matches in a local part list
2829 */
2830
2831 case ECOND_MATCH_ADDRESS:
2832 case ECOND_MATCH_DOMAIN:
2833 case ECOND_MATCH_IP:
2834 case ECOND_MATCH_LOCAL_PART:
2835 #ifndef EXPAND_LISTMATCH_RHS
2836 sub2_honour_dollar = FALSE;
2837 #endif
2838 /* FALLTHROUGH */
2839
2840 case ECOND_CRYPTEQ:
2841 case ECOND_INLIST:
2842 case ECOND_INLISTI:
2843 case ECOND_MATCH:
2844
2845 case ECOND_NUM_L: /* Numerical comparisons */
2846 case ECOND_NUM_LE:
2847 case ECOND_NUM_E:
2848 case ECOND_NUM_EE:
2849 case ECOND_NUM_G:
2850 case ECOND_NUM_GE:
2851
2852 case ECOND_STR_LT: /* String comparisons */
2853 case ECOND_STR_LTI:
2854 case ECOND_STR_LE:
2855 case ECOND_STR_LEI:
2856 case ECOND_STR_EQ:
2857 case ECOND_STR_EQI:
2858 case ECOND_STR_GT:
2859 case ECOND_STR_GTI:
2860 case ECOND_STR_GE:
2861 case ECOND_STR_GEI:
2862
2863 for (int i = 0; i < 2; i++)
2864 {
2865 /* Sometimes, we don't expand substrings; too many insecure configurations
2866 created using match_address{}{} and friends, where the second param
2867 includes information from untrustworthy sources. */
2868 BOOL honour_dollar = TRUE;
2869 if ((i > 0) && !sub2_honour_dollar)
2870 honour_dollar = FALSE;
2871
2872 if (Uskip_whitespace(&s) != '{')
2873 {
2874 if (i == 0) goto COND_FAILED_CURLY_START;
2875 expand_string_message = string_sprintf("missing 2nd string in {} "
2876 "after \"%s\"", opname);
2877 return NULL;
2878 }
2879 if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL,
2880 honour_dollar, resetok)))
2881 return NULL;
2882 DEBUG(D_expand) if (i == 1 && !sub2_honour_dollar && Ustrchr(sub[1], '$'))
2883 debug_printf_indent("WARNING: the second arg is NOT expanded,"
2884 " for security reasons\n");
2885 if (*s++ != '}') goto COND_FAILED_CURLY_END;
2886
2887 /* Convert to numerical if required; we know that the names of all the
2888 conditions that compare numbers do not start with a letter. This just saves
2889 checking for them individually. */
2890
2891 if (!isalpha(opname[0]) && yield)
2892 if (sub[i][0] == 0)
2893 {
2894 num[i] = 0;
2895 DEBUG(D_expand)
2896 debug_printf_indent("empty string cast to zero for numerical comparison\n");
2897 }
2898 else
2899 {
2900 num[i] = expanded_string_integer(sub[i], FALSE);
2901 if (expand_string_message) return NULL;
2902 }
2903 }
2904
2905 /* Result not required */
2906
2907 if (!yield) return s;
2908
2909 /* Do an appropriate comparison */
2910
2911 switch(cond_type)
2912 {
2913 case ECOND_NUM_E:
2914 case ECOND_NUM_EE:
2915 tempcond = (num[0] == num[1]);
2916 break;
2917
2918 case ECOND_NUM_G:
2919 tempcond = (num[0] > num[1]);
2920 break;
2921
2922 case ECOND_NUM_GE:
2923 tempcond = (num[0] >= num[1]);
2924 break;
2925
2926 case ECOND_NUM_L:
2927 tempcond = (num[0] < num[1]);
2928 break;
2929
2930 case ECOND_NUM_LE:
2931 tempcond = (num[0] <= num[1]);
2932 break;
2933
2934 case ECOND_STR_LT:
2935 tempcond = (Ustrcmp(sub[0], sub[1]) < 0);
2936 break;
2937
2938 case ECOND_STR_LTI:
2939 tempcond = (strcmpic(sub[0], sub[1]) < 0);
2940 break;
2941
2942 case ECOND_STR_LE:
2943 tempcond = (Ustrcmp(sub[0], sub[1]) <= 0);
2944 break;
2945
2946 case ECOND_STR_LEI:
2947 tempcond = (strcmpic(sub[0], sub[1]) <= 0);
2948 break;
2949
2950 case ECOND_STR_EQ:
2951 tempcond = (Ustrcmp(sub[0], sub[1]) == 0);
2952 break;
2953
2954 case ECOND_STR_EQI:
2955 tempcond = (strcmpic(sub[0], sub[1]) == 0);
2956 break;
2957
2958 case ECOND_STR_GT:
2959 tempcond = (Ustrcmp(sub[0], sub[1]) > 0);
2960 break;
2961
2962 case ECOND_STR_GTI:
2963 tempcond = (strcmpic(sub[0], sub[1]) > 0);
2964 break;
2965
2966 case ECOND_STR_GE:
2967 tempcond = (Ustrcmp(sub[0], sub[1]) >= 0);
2968 break;
2969
2970 case ECOND_STR_GEI:
2971 tempcond = (strcmpic(sub[0], sub[1]) >= 0);
2972 break;
2973
2974 case ECOND_MATCH: /* Regular expression match */
2975 if (!(re = pcre_compile(CS sub[1], PCRE_COPT, CCSS &rerror,
2976 &roffset, NULL)))
2977 {
2978 expand_string_message = string_sprintf("regular expression error in "
2979 "\"%s\": %s at offset %d", sub[1], rerror, roffset);
2980 return NULL;
2981 }
2982 tempcond = regex_match_and_setup(re, sub[0], 0, -1);
2983 break;
2984
2985 case ECOND_MATCH_ADDRESS: /* Match in an address list */
2986 rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0, NULL);
2987 goto MATCHED_SOMETHING;
2988
2989 case ECOND_MATCH_DOMAIN: /* Match in a domain list */
2990 rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
2991 MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
2992 goto MATCHED_SOMETHING;
2993
2994 case ECOND_MATCH_IP: /* Match IP address in a host list */
2995 if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) == 0)
2996 {
2997 expand_string_message = string_sprintf("\"%s\" is not an IP address",
2998 sub[0]);
2999 return NULL;
3000 }
3001 else
3002 {
3003 unsigned int *nullcache = NULL;
3004 check_host_block cb;
3005
3006 cb.host_name = US"";
3007 cb.host_address = sub[0];
3008
3009 /* If the host address starts off ::ffff: it is an IPv6 address in
3010 IPv4-compatible mode. Find the IPv4 part for checking against IPv4
3011 addresses. */
3012
3013 cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
3014 cb.host_address + 7 : cb.host_address;
3015
3016 rc = match_check_list(
3017 &sub[1], /* the list */
3018 0, /* separator character */
3019 &hostlist_anchor, /* anchor pointer */
3020 &nullcache, /* cache pointer */
3021 check_host, /* function for testing */
3022 &cb, /* argument for function */
3023 MCL_HOST, /* type of check */
3024 sub[0], /* text for debugging */
3025 NULL); /* where to pass back data */
3026 }
3027 goto MATCHED_SOMETHING;
3028
3029 case ECOND_MATCH_LOCAL_PART:
3030 rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
3031 MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
3032 /* Fall through */
3033 /* VVVVVVVVVVVV */
3034 MATCHED_SOMETHING:
3035 switch(rc)
3036 {
3037 case OK:
3038 tempcond = TRUE;
3039 break;
3040
3041 case FAIL:
3042 tempcond = FALSE;
3043 break;
3044
3045 case DEFER:
3046 expand_string_message = string_sprintf("unable to complete match "
3047 "against \"%s\": %s", sub[1], search_error_message);
3048 return NULL;
3049 }
3050
3051 break;
3052
3053 /* Various "encrypted" comparisons. If the second string starts with
3054 "{" then an encryption type is given. Default to crypt() or crypt16()
3055 (build-time choice). */
3056 /* }-for-text-editors */
3057
3058 case ECOND_CRYPTEQ:
3059 #ifndef SUPPORT_CRYPTEQ
3060 goto COND_FAILED_NOT_COMPILED;
3061 #else
3062 if (strncmpic(sub[1], US"{md5}", 5) == 0)
3063 {
3064 int sublen = Ustrlen(sub[1]+5);
3065 md5 base;
3066 uschar digest[16];
3067
3068 md5_start(&base);
3069 md5_end(&base, sub[0], Ustrlen(sub[0]), digest);
3070
3071 /* If the length that we are comparing against is 24, the MD5 digest
3072 is expressed as a base64 string. This is the way LDAP does it. However,
3073 some other software uses a straightforward hex representation. We assume
3074 this if the length is 32. Other lengths fail. */
3075
3076 if (sublen == 24)
3077 {
3078 uschar *coded = b64encode(CUS digest, 16);
3079 DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
3080 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
3081 tempcond = (Ustrcmp(coded, sub[1]+5) == 0);
3082 }
3083 else if (sublen == 32)
3084 {
3085 uschar coded[36];
3086 for (int i = 0; i < 16; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3087 coded[32] = 0;
3088 DEBUG(D_auth) debug_printf("crypteq: using MD5+hex hashing\n"
3089 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
3090 tempcond = (strcmpic(coded, sub[1]+5) == 0);
3091 }
3092 else
3093 {
3094 DEBUG(D_auth) debug_printf("crypteq: length for MD5 not 24 or 32: "
3095 "fail\n crypted=%s\n", sub[1]+5);
3096 tempcond = FALSE;
3097 }
3098 }
3099
3100 else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
3101 {
3102 int sublen = Ustrlen(sub[1]+6);
3103 hctx h;
3104 uschar digest[20];
3105
3106 sha1_start(&h);
3107 sha1_end(&h, sub[0], Ustrlen(sub[0]), digest);
3108
3109 /* If the length that we are comparing against is 28, assume the SHA1
3110 digest is expressed as a base64 string. If the length is 40, assume a
3111 straightforward hex representation. Other lengths fail. */
3112
3113 if (sublen == 28)
3114 {
3115 uschar *coded = b64encode(CUS digest, 20);
3116 DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
3117 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
3118 tempcond = (Ustrcmp(coded, sub[1]+6) == 0);
3119 }
3120 else if (sublen == 40)
3121 {
3122 uschar coded[44];
3123 for (int i = 0; i < 20; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3124 coded[40] = 0;
3125 DEBUG(D_auth) debug_printf("crypteq: using SHA1+hex hashing\n"
3126 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
3127 tempcond = (strcmpic(coded, sub[1]+6) == 0);
3128 }
3129 else
3130 {
3131 DEBUG(D_auth) debug_printf("crypteq: length for SHA-1 not 28 or 40: "
3132 "fail\n crypted=%s\n", sub[1]+6);
3133 tempcond = FALSE;
3134 }
3135 }
3136
3137 else /* {crypt} or {crypt16} and non-{ at start */
3138 /* }-for-text-editors */
3139 {
3140 int which = 0;
3141 uschar *coded;
3142
3143 if (strncmpic(sub[1], US"{crypt}", 7) == 0)
3144 {
3145 sub[1] += 7;
3146 which = 1;
3147 }
3148 else if (strncmpic(sub[1], US"{crypt16}", 9) == 0)
3149 {
3150 sub[1] += 9;
3151 which = 2;
3152 }
3153 else if (sub[1][0] == '{') /* }-for-text-editors */
3154 {
3155 expand_string_message = string_sprintf("unknown encryption mechanism "
3156 "in \"%s\"", sub[1]);
3157 return NULL;
3158 }
3159
3160 switch(which)
3161 {
3162 case 0: coded = US DEFAULT_CRYPT(CS sub[0], CS sub[1]); break;
3163 case 1: coded = US crypt(CS sub[0], CS sub[1]); break;
3164 default: coded = US crypt16(CS sub[0], CS sub[1]); break;
3165 }
3166
3167 #define STR(s) # s
3168 #define XSTR(s) STR(s)
3169 DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
3170 " subject=%s\n crypted=%s\n",
3171 which == 0 ? XSTR(DEFAULT_CRYPT) : which == 1 ? "crypt" : "crypt16",
3172 coded, sub[1]);
3173 #undef STR
3174 #undef XSTR
3175
3176 /* If the encrypted string contains fewer than two characters (for the
3177 salt), force failure. Otherwise we get false positives: with an empty
3178 string the yield of crypt() is an empty string! */
3179
3180 if (coded)
3181 tempcond = Ustrlen(sub[1]) < 2 ? FALSE : Ustrcmp(coded, sub[1]) == 0;
3182 else if (errno == EINVAL)
3183 tempcond = FALSE;
3184 else
3185 {
3186 expand_string_message = string_sprintf("crypt error: %s\n",
3187 US strerror(errno));
3188 return NULL;
3189 }
3190 }
3191 break;
3192 #endif /* SUPPORT_CRYPTEQ */
3193
3194 case ECOND_INLIST:
3195 case ECOND_INLISTI:
3196 {
3197 const uschar * list = sub[1];
3198 int sep = 0;
3199 uschar *save_iterate_item = iterate_item;
3200 int (*compare)(const uschar *, const uschar *);
3201
3202 DEBUG(D_expand) debug_printf_indent("condition: %s item: %s\n", opname, sub[0]);
3203
3204 tempcond = FALSE;
3205 compare = cond_type == ECOND_INLISTI
3206 ? strcmpic : (int (*)(const uschar *, const uschar *)) strcmp;
3207
3208 while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
3209 {
3210 DEBUG(D_expand) debug_printf_indent(" compare %s\n", iterate_item);
3211 if (compare(sub[0], iterate_item) == 0)
3212 {
3213 tempcond = TRUE;
3214 break;
3215 }
3216 }
3217 iterate_item = save_iterate_item;
3218 }
3219
3220 } /* Switch for comparison conditions */
3221
3222 *yield = tempcond == testfor;
3223 return s; /* End of comparison conditions */
3224
3225
3226 /* and/or: computes logical and/or of several conditions */
3227
3228 case ECOND_AND:
3229 case ECOND_OR:
3230 subcondptr = (yield == NULL) ? NULL : &tempcond;
3231 combined_cond = (cond_type == ECOND_AND);
3232
3233 Uskip_whitespace(&s);
3234 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3235
3236 for (;;)
3237 {
3238 /* {-for-text-editors */
3239 if (Uskip_whitespace(&s) == '}') break;
3240 if (*s != '{') /* }-for-text-editors */
3241 {
3242 expand_string_message = string_sprintf("each subcondition "
3243 "inside an \"%s{...}\" condition must be in its own {}", opname);
3244 return NULL;
3245 }
3246
3247 if (!(s = eval_condition(s+1, resetok, subcondptr)))
3248 {
3249 expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
3250 expand_string_message, opname);
3251 return NULL;
3252 }
3253 Uskip_whitespace(&s);
3254
3255 /* {-for-text-editors */
3256 if (*s++ != '}')
3257 {
3258 /* {-for-text-editors */
3259 expand_string_message = string_sprintf("missing } at end of condition "
3260 "inside \"%s\" group", opname);
3261 return NULL;
3262 }
3263
3264 if (yield)
3265 if (cond_type == ECOND_AND)
3266 {
3267 combined_cond &= tempcond;
3268 if (!combined_cond) subcondptr = NULL; /* once false, don't */
3269 } /* evaluate any more */
3270 else
3271 {
3272 combined_cond |= tempcond;
3273 if (combined_cond) subcondptr = NULL; /* once true, don't */
3274 } /* evaluate any more */
3275 }
3276
3277 if (yield) *yield = (combined_cond == testfor);
3278 return ++s;
3279
3280
3281 /* forall/forany: iterates a condition with different values */
3282
3283 case ECOND_FORALL: is_forany = FALSE; is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3284 case ECOND_FORANY: is_forany = TRUE; is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3285 case ECOND_FORALL_JSON: is_forany = FALSE; is_json = TRUE; is_jsons = FALSE; goto FORMANY;
3286 case ECOND_FORANY_JSON: is_forany = TRUE; is_json = TRUE; is_jsons = FALSE; goto FORMANY;
3287 case ECOND_FORALL_JSONS: is_forany = FALSE; is_json = TRUE; is_jsons = TRUE; goto FORMANY;
3288 case ECOND_FORANY_JSONS: is_forany = TRUE; is_json = TRUE; is_jsons = TRUE; goto FORMANY;
3289
3290 FORMANY:
3291 {
3292 const uschar * list;
3293 int sep = 0;
3294 uschar *save_iterate_item = iterate_item;
3295
3296 DEBUG(D_expand) debug_printf_indent("condition: %s\n", opname);
3297
3298 Uskip_whitespace(&s);
3299 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3300 if (!(sub[0] = expand_string_internal(s, TRUE, &s, yield == NULL, TRUE, resetok)))
3301 return NULL;
3302 /* {-for-text-editors */
3303 if (*s++ != '}') goto COND_FAILED_CURLY_END;
3304
3305 Uskip_whitespace(&s);
3306 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3307
3308 sub[1] = s;
3309
3310 /* Call eval_condition once, with result discarded (as if scanning a
3311 "false" part). This allows us to find the end of the condition, because if
3312 the list it empty, we won't actually evaluate the condition for real. */
3313
3314 if (!(s = eval_condition(sub[1], resetok, NULL)))
3315 {
3316 expand_string_message = string_sprintf("%s inside \"%s\" condition",
3317 expand_string_message, opname);
3318 return NULL;
3319 }
3320 Uskip_whitespace(&s);
3321
3322 /* {-for-text-editors */
3323 if (*s++ != '}')
3324 {
3325 /* {-for-text-editors */
3326 expand_string_message = string_sprintf("missing } at end of condition "
3327 "inside \"%s\"", opname);
3328 return NULL;
3329 }
3330
3331 if (yield) *yield = !testfor;
3332 list = sub[0];
3333 if (is_json) list = dewrap(string_copy(list), US"[]");
3334 while ((iterate_item = is_json
3335 ? json_nextinlist(&list) : string_nextinlist(&list, &sep, NULL, 0)))
3336 {
3337 if (is_jsons)
3338 if (!(iterate_item = dewrap(iterate_item, US"\"\"")))
3339 {
3340 expand_string_message =
3341 string_sprintf("%s wrapping string result for extract jsons",
3342 expand_string_message);
3343 iterate_item = save_iterate_item;
3344 return NULL;
3345 }
3346
3347 DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", opname, iterate_item);
3348 if (!eval_condition(sub[1], resetok, &tempcond))
3349 {
3350 expand_string_message = string_sprintf("%s insid