6d43774f18c1c3d78c41b5a98107bdb6dcecd295
[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 uschar *
1176 expand_getkeyed(const uschar * key, const uschar * s)
1177 {
1178 int length = Ustrlen(key);
1179 Uskip_whitespace(&s);
1180
1181 /* Loop to search for the key */
1182
1183 while (*s)
1184 {
1185 int dkeylength;
1186 uschar * data;
1187 const uschar * dkey = s;
1188
1189 while (*s && *s != '=' && !isspace(*s)) s++;
1190 dkeylength = s - dkey;
1191 if (Uskip_whitespace(&s) == '=') while (isspace(*++s));
1192
1193 data = string_dequote(&s);
1194 if (length == dkeylength && strncmpic(key, dkey, length) == 0)
1195 return data;
1196
1197 Uskip_whitespace(&s);
1198 }
1199
1200 return NULL;
1201 }
1202
1203
1204
1205 static var_entry *
1206 find_var_ent(uschar * name)
1207 {
1208 int first = 0;
1209 int last = var_table_size;
1210
1211 while (last > first)
1212 {
1213 int middle = (first + last)/2;
1214 int c = Ustrcmp(name, var_table[middle].name);
1215
1216 if (c > 0) { first = middle + 1; continue; }
1217 if (c < 0) { last = middle; continue; }
1218 return &var_table[middle];
1219 }
1220 return NULL;
1221 }
1222
1223 /*************************************************
1224 * Extract numbered subfield from string *
1225 *************************************************/
1226
1227 /* Extracts a numbered field from a string that is divided by tokens - for
1228 example a line from /etc/passwd is divided by colon characters. First field is
1229 numbered one. Negative arguments count from the right. Zero returns the whole
1230 string. Returns NULL if there are insufficient tokens in the string
1231
1232 ***WARNING***
1233 Modifies final argument - this is a dynamically generated string, so that's OK.
1234
1235 Arguments:
1236 field number of field to be extracted,
1237 first field = 1, whole string = 0, last field = -1
1238 separators characters that are used to break string into tokens
1239 s points to the string from which to extract the subfield
1240
1241 Returns: NULL if the field was not found,
1242 a pointer to the field's data inside s (modified to add 0)
1243 */
1244
1245 static uschar *
1246 expand_gettokened (int field, uschar *separators, uschar *s)
1247 {
1248 int sep = 1;
1249 int count;
1250 uschar *ss = s;
1251 uschar *fieldtext = NULL;
1252
1253 if (field == 0) return s;
1254
1255 /* Break the line up into fields in place; for field > 0 we stop when we have
1256 done the number of fields we want. For field < 0 we continue till the end of
1257 the string, counting the number of fields. */
1258
1259 count = (field > 0)? field : INT_MAX;
1260
1261 while (count-- > 0)
1262 {
1263 size_t len;
1264
1265 /* Previous field was the last one in the string. For a positive field
1266 number, this means there are not enough fields. For a negative field number,
1267 check that there are enough, and scan back to find the one that is wanted. */
1268
1269 if (sep == 0)
1270 {
1271 if (field > 0 || (-field) > (INT_MAX - count - 1)) return NULL;
1272 if ((-field) == (INT_MAX - count - 1)) return s;
1273 while (field++ < 0)
1274 {
1275 ss--;
1276 while (ss[-1] != 0) ss--;
1277 }
1278 fieldtext = ss;
1279 break;
1280 }
1281
1282 /* Previous field was not last in the string; save its start and put a
1283 zero at its end. */
1284
1285 fieldtext = ss;
1286 len = Ustrcspn(ss, separators);
1287 sep = ss[len];
1288 ss[len] = 0;
1289 ss += len + 1;
1290 }
1291
1292 return fieldtext;
1293 }
1294
1295
1296 static uschar *
1297 expand_getlistele(int field, const uschar * list)
1298 {
1299 const uschar * tlist = list;
1300 int sep = 0;
1301 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 #ifdef EXPERIMENTAL_SRS_NATIVE
2442 /* Do an hmac_md5. The result is _not_ nul-terminated, and is sized as
2443 the smaller of a full hmac_md5 result (16 bytes) or the supplied output buffer.
2444
2445 Arguments:
2446 key encoding key, nul-terminated
2447 src data to be hashed, nul-terminated
2448 buf output buffer
2449 len size of output buffer
2450 */
2451
2452 static void
2453 hmac_md5(const uschar * key, const uschar * src, uschar * buf, unsigned len)
2454 {
2455 md5 md5_base;
2456 const uschar * keyptr;
2457 uschar * p;
2458 unsigned int keylen;
2459
2460 #define MD5_HASHLEN 16
2461 #define MD5_HASHBLOCKLEN 64
2462
2463 uschar keyhash[MD5_HASHLEN];
2464 uschar innerhash[MD5_HASHLEN];
2465 uschar finalhash[MD5_HASHLEN];
2466 uschar innerkey[MD5_HASHBLOCKLEN];
2467 uschar outerkey[MD5_HASHBLOCKLEN];
2468
2469 keyptr = key;
2470 keylen = Ustrlen(keyptr);
2471
2472 /* If the key is longer than the hash block length, then hash the key
2473 first */
2474
2475 if (keylen > MD5_HASHBLOCKLEN)
2476 {
2477 chash_start(HMAC_MD5, &md5_base);
2478 chash_end(HMAC_MD5, &md5_base, keyptr, keylen, keyhash);
2479 keyptr = keyhash;
2480 keylen = MD5_HASHLEN;
2481 }
2482
2483 /* Now make the inner and outer key values */
2484
2485 memset(innerkey, 0x36, MD5_HASHBLOCKLEN);
2486 memset(outerkey, 0x5c, MD5_HASHBLOCKLEN);
2487
2488 for (int i = 0; i < keylen; i++)
2489 {
2490 innerkey[i] ^= keyptr[i];
2491 outerkey[i] ^= keyptr[i];
2492 }
2493
2494 /* Now do the hashes */
2495
2496 chash_start(HMAC_MD5, &md5_base);
2497 chash_mid(HMAC_MD5, &md5_base, innerkey);
2498 chash_end(HMAC_MD5, &md5_base, src, Ustrlen(src), innerhash);
2499
2500 chash_start(HMAC_MD5, &md5_base);
2501 chash_mid(HMAC_MD5, &md5_base, outerkey);
2502 chash_end(HMAC_MD5, &md5_base, innerhash, MD5_HASHLEN, finalhash);
2503
2504 /* Encode the final hash as a hex string, limited by output buffer size */
2505
2506 p = buf;
2507 for (int i = 0, j = len; i < MD5_HASHLEN; i++)
2508 {
2509 if (j-- <= 0) break;
2510 *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
2511 if (j-- <= 0) break;
2512 *p++ = hex_digits[finalhash[i] & 0x0f];
2513 }
2514 return;
2515 }
2516 #endif /*EXPERIMENTAL_SRS_NATIVE*/
2517
2518
2519 /*************************************************
2520 * Read and evaluate a condition *
2521 *************************************************/
2522
2523 /*
2524 Arguments:
2525 s points to the start of the condition text
2526 resetok points to a BOOL which is written false if it is unsafe to
2527 free memory. Certain condition types (acl) may have side-effect
2528 allocation which must be preserved.
2529 yield points to a BOOL to hold the result of the condition test;
2530 if NULL, we are just reading through a condition that is
2531 part of an "or" combination to check syntax, or in a state
2532 where the answer isn't required
2533
2534 Returns: a pointer to the first character after the condition, or
2535 NULL after an error
2536 */
2537
2538 static const uschar *
2539 eval_condition(const uschar *s, BOOL *resetok, BOOL *yield)
2540 {
2541 BOOL testfor = TRUE;
2542 BOOL tempcond, combined_cond;
2543 BOOL *subcondptr;
2544 BOOL sub2_honour_dollar = TRUE;
2545 BOOL is_forany, is_json, is_jsons;
2546 int rc, cond_type, roffset;
2547 int_eximarith_t num[2];
2548 struct stat statbuf;
2549 uschar * opname;
2550 uschar name[256];
2551 const uschar *sub[10];
2552
2553 const pcre *re;
2554 const uschar *rerror;
2555
2556 for (;;)
2557 if (Uskip_whitespace(&s) == '!') { testfor = !testfor; s++; } else break;
2558
2559 switch(cond_type = identify_operator(&s, &opname))
2560 {
2561 /* def: tests for a non-empty variable, or for the existence of a header. If
2562 yield == NULL we are in a skipping state, and don't care about the answer. */
2563
2564 case ECOND_DEF:
2565 {
2566 uschar * t;
2567
2568 if (*s != ':')
2569 {
2570 expand_string_message = US"\":\" expected after \"def\"";
2571 return NULL;
2572 }
2573
2574 s = read_name(name, sizeof(name), s+1, US"_");
2575
2576 /* Test for a header's existence. If the name contains a closing brace
2577 character, this may be a user error where the terminating colon has been
2578 omitted. Set a flag to adjust a subsequent error message in this case. */
2579
2580 if ( ( *(t = name) == 'h'
2581 || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
2582 )
2583 && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
2584 )
2585 {
2586 s = read_header_name(name, sizeof(name), s);
2587 /* {-for-text-editors */
2588 if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
2589 if (yield) *yield =
2590 (find_header(name, NULL, FH_EXISTS_ONLY, NULL) != NULL) == testfor;
2591 }
2592
2593 /* Test for a variable's having a non-empty value. A non-existent variable
2594 causes an expansion failure. */
2595
2596 else
2597 {
2598 if (!(t = find_variable(name, TRUE, yield == NULL, NULL)))
2599 {
2600 expand_string_message = name[0]
2601 ? string_sprintf("unknown variable \"%s\" after \"def:\"", name)
2602 : US"variable name omitted after \"def:\"";
2603 check_variable_error_message(name);
2604 return NULL;
2605 }
2606 if (yield) *yield = (t[0] != 0) == testfor;
2607 }
2608
2609 return s;
2610 }
2611
2612
2613 /* first_delivery tests for first delivery attempt */
2614
2615 case ECOND_FIRST_DELIVERY:
2616 if (yield) *yield = f.deliver_firsttime == testfor;
2617 return s;
2618
2619
2620 /* queue_running tests for any process started by a queue runner */
2621
2622 case ECOND_QUEUE_RUNNING:
2623 if (yield) *yield = (queue_run_pid != (pid_t)0) == testfor;
2624 return s;
2625
2626
2627 /* exists: tests for file existence
2628 isip: tests for any IP address
2629 isip4: tests for an IPv4 address
2630 isip6: tests for an IPv6 address
2631 pam: does PAM authentication
2632 radius: does RADIUS authentication
2633 ldapauth: does LDAP authentication
2634 pwcheck: does Cyrus SASL pwcheck authentication
2635 */
2636
2637 case ECOND_EXISTS:
2638 case ECOND_ISIP:
2639 case ECOND_ISIP4:
2640 case ECOND_ISIP6:
2641 case ECOND_PAM:
2642 case ECOND_RADIUS:
2643 case ECOND_LDAPAUTH:
2644 case ECOND_PWCHECK:
2645
2646 if (Uskip_whitespace(&s) != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2647
2648 sub[0] = expand_string_internal(s+1, TRUE, &s, yield == NULL, TRUE, resetok);
2649 if (!sub[0]) return NULL;
2650 /* {-for-text-editors */
2651 if (*s++ != '}') goto COND_FAILED_CURLY_END;
2652
2653 if (!yield) return s; /* No need to run the test if skipping */
2654
2655 switch(cond_type)
2656 {
2657 case ECOND_EXISTS:
2658 if ((expand_forbid & RDO_EXISTS) != 0)
2659 {
2660 expand_string_message = US"File existence tests are not permitted";
2661 return NULL;
2662 }
2663 *yield = (Ustat(sub[0], &statbuf) == 0) == testfor;
2664 break;
2665
2666 case ECOND_ISIP:
2667 case ECOND_ISIP4:
2668 case ECOND_ISIP6:
2669 rc = string_is_ip_address(sub[0], NULL);
2670 *yield = ((cond_type == ECOND_ISIP)? (rc != 0) :
2671 (cond_type == ECOND_ISIP4)? (rc == 4) : (rc == 6)) == testfor;
2672 break;
2673
2674 /* Various authentication tests - all optionally compiled */
2675
2676 case ECOND_PAM:
2677 #ifdef SUPPORT_PAM
2678 rc = auth_call_pam(sub[0], &expand_string_message);
2679 goto END_AUTH;
2680 #else
2681 goto COND_FAILED_NOT_COMPILED;
2682 #endif /* SUPPORT_PAM */
2683
2684 case ECOND_RADIUS:
2685 #ifdef RADIUS_CONFIG_FILE
2686 rc = auth_call_radius(sub[0], &expand_string_message);
2687 goto END_AUTH;
2688 #else
2689 goto COND_FAILED_NOT_COMPILED;
2690 #endif /* RADIUS_CONFIG_FILE */
2691
2692 case ECOND_LDAPAUTH:
2693 #ifdef LOOKUP_LDAP
2694 {
2695 /* Just to keep the interface the same */
2696 BOOL do_cache;
2697 int old_pool = store_pool;
2698 store_pool = POOL_SEARCH;
2699 rc = eldapauth_find((void *)(-1), NULL, sub[0], Ustrlen(sub[0]), NULL,
2700 &expand_string_message, &do_cache);
2701 store_pool = old_pool;
2702 }
2703 goto END_AUTH;
2704 #else
2705 goto COND_FAILED_NOT_COMPILED;
2706 #endif /* LOOKUP_LDAP */
2707
2708 case ECOND_PWCHECK:
2709 #ifdef CYRUS_PWCHECK_SOCKET
2710 rc = auth_call_pwcheck(sub[0], &expand_string_message);
2711 goto END_AUTH;
2712 #else
2713 goto COND_FAILED_NOT_COMPILED;
2714 #endif /* CYRUS_PWCHECK_SOCKET */
2715
2716 #if defined(SUPPORT_PAM) || defined(RADIUS_CONFIG_FILE) || \
2717 defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET)
2718 END_AUTH:
2719 if (rc == ERROR || rc == DEFER) return NULL;
2720 *yield = (rc == OK) == testfor;
2721 #endif
2722 }
2723 return s;
2724
2725
2726 /* call ACL (in a conditional context). Accept true, deny false.
2727 Defer is a forced-fail. Anything set by message= goes to $value.
2728 Up to ten parameters are used; we use the braces round the name+args
2729 like the saslauthd condition does, to permit a variable number of args.
2730 See also the expansion-item version EITEM_ACL and the traditional
2731 acl modifier ACLC_ACL.
2732 Since the ACL may allocate new global variables, tell our caller to not
2733 reclaim memory.
2734 */
2735
2736 case ECOND_ACL:
2737 /* ${if acl {{name}{arg1}{arg2}...} {yes}{no}} */
2738 {
2739 uschar *sub[10];
2740 uschar *user_msg;
2741 BOOL cond = FALSE;
2742
2743 Uskip_whitespace(&s);
2744 if (*s++ != '{') goto COND_FAILED_CURLY_START; /*}*/
2745
2746 switch(read_subs(sub, nelem(sub), 1,
2747 &s, yield == NULL, TRUE, name, resetok))
2748 {
2749 case 1: expand_string_message = US"too few arguments or bracketing "
2750 "error for acl";
2751 case 2:
2752 case 3: return NULL;
2753 }
2754
2755 if (yield)
2756 {
2757 int rc;
2758 *resetok = FALSE; /* eval_acl() might allocate; do not reclaim */
2759 switch(rc = eval_acl(sub, nelem(sub), &user_msg))
2760 {
2761 case OK:
2762 cond = TRUE;
2763 case FAIL:
2764 lookup_value = NULL;
2765 if (user_msg)
2766 lookup_value = string_copy(user_msg);
2767 *yield = cond == testfor;
2768 break;
2769
2770 case DEFER:
2771 f.expand_string_forcedfail = TRUE;
2772 /*FALLTHROUGH*/
2773 default:
2774 expand_string_message = string_sprintf("%s from acl \"%s\"",
2775 rc_names[rc], sub[0]);
2776 return NULL;
2777 }
2778 }
2779 return s;
2780 }
2781
2782
2783 /* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
2784
2785 ${if saslauthd {{username}{password}{service}{realm}} {yes}{no}}
2786
2787 However, the last two are optional. That is why the whole set is enclosed
2788 in their own set of braces. */
2789
2790 case ECOND_SASLAUTHD:
2791 #ifndef CYRUS_SASLAUTHD_SOCKET
2792 goto COND_FAILED_NOT_COMPILED;
2793 #else
2794 {
2795 uschar *sub[4];
2796 Uskip_whitespace(&s);
2797 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
2798 switch(read_subs(sub, nelem(sub), 2, &s, yield == NULL, TRUE, name,
2799 resetok))
2800 {
2801 case 1: expand_string_message = US"too few arguments or bracketing "
2802 "error for saslauthd";
2803 case 2:
2804 case 3: return NULL;
2805 }
2806 if (!sub[2]) sub[3] = NULL; /* realm if no service */
2807 if (yield)
2808 {
2809 int rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
2810 &expand_string_message);
2811 if (rc == ERROR || rc == DEFER) return NULL;
2812 *yield = (rc == OK) == testfor;
2813 }
2814 return s;
2815 }
2816 #endif /* CYRUS_SASLAUTHD_SOCKET */
2817
2818
2819 /* symbolic operators for numeric and string comparison, and a number of
2820 other operators, all requiring two arguments.
2821
2822 crypteq: encrypts plaintext and compares against an encrypted text,
2823 using crypt(), crypt16(), MD5 or SHA-1
2824 inlist/inlisti: checks if first argument is in the list of the second
2825 match: does a regular expression match and sets up the numerical
2826 variables if it succeeds
2827 match_address: matches in an address list
2828 match_domain: matches in a domain list
2829 match_ip: matches a host list that is restricted to IP addresses
2830 match_local_part: matches in a local part list
2831 */
2832
2833 case ECOND_MATCH_ADDRESS:
2834 case ECOND_MATCH_DOMAIN:
2835 case ECOND_MATCH_IP:
2836 case ECOND_MATCH_LOCAL_PART:
2837 #ifndef EXPAND_LISTMATCH_RHS
2838 sub2_honour_dollar = FALSE;
2839 #endif
2840 /* FALLTHROUGH */
2841
2842 case ECOND_CRYPTEQ:
2843 case ECOND_INLIST:
2844 case ECOND_INLISTI:
2845 case ECOND_MATCH:
2846
2847 case ECOND_NUM_L: /* Numerical comparisons */
2848 case ECOND_NUM_LE:
2849 case ECOND_NUM_E:
2850 case ECOND_NUM_EE:
2851 case ECOND_NUM_G:
2852 case ECOND_NUM_GE:
2853
2854 case ECOND_STR_LT: /* String comparisons */
2855 case ECOND_STR_LTI:
2856 case ECOND_STR_LE:
2857 case ECOND_STR_LEI:
2858 case ECOND_STR_EQ:
2859 case ECOND_STR_EQI:
2860 case ECOND_STR_GT:
2861 case ECOND_STR_GTI:
2862 case ECOND_STR_GE:
2863 case ECOND_STR_GEI:
2864
2865 for (int i = 0; i < 2; i++)
2866 {
2867 /* Sometimes, we don't expand substrings; too many insecure configurations
2868 created using match_address{}{} and friends, where the second param
2869 includes information from untrustworthy sources. */
2870 BOOL honour_dollar = TRUE;
2871 if ((i > 0) && !sub2_honour_dollar)
2872 honour_dollar = FALSE;
2873
2874 if (Uskip_whitespace(&s) != '{')
2875 {
2876 if (i == 0) goto COND_FAILED_CURLY_START;
2877 expand_string_message = string_sprintf("missing 2nd string in {} "
2878 "after \"%s\"", opname);
2879 return NULL;
2880 }
2881 if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL,
2882 honour_dollar, resetok)))
2883 return NULL;
2884 DEBUG(D_expand) if (i == 1 && !sub2_honour_dollar && Ustrchr(sub[1], '$'))
2885 debug_printf_indent("WARNING: the second arg is NOT expanded,"
2886 " for security reasons\n");
2887 if (*s++ != '}') goto COND_FAILED_CURLY_END;
2888
2889 /* Convert to numerical if required; we know that the names of all the
2890 conditions that compare numbers do not start with a letter. This just saves
2891 checking for them individually. */
2892
2893 if (!isalpha(opname[0]) && yield)
2894 if (sub[i][0] == 0)
2895 {
2896 num[i] = 0;
2897 DEBUG(D_expand)
2898 debug_printf_indent("empty string cast to zero for numerical comparison\n");
2899 }
2900 else
2901 {
2902 num[i] = expanded_string_integer(sub[i], FALSE);
2903 if (expand_string_message) return NULL;
2904 }
2905 }
2906
2907 /* Result not required */
2908
2909 if (!yield) return s;
2910
2911 /* Do an appropriate comparison */
2912
2913 switch(cond_type)
2914 {
2915 case ECOND_NUM_E:
2916 case ECOND_NUM_EE:
2917 tempcond = (num[0] == num[1]);
2918 break;
2919
2920 case ECOND_NUM_G:
2921 tempcond = (num[0] > num[1]);
2922 break;
2923
2924 case ECOND_NUM_GE:
2925 tempcond = (num[0] >= num[1]);
2926 break;
2927
2928 case ECOND_NUM_L:
2929 tempcond = (num[0] < num[1]);
2930 break;
2931
2932 case ECOND_NUM_LE:
2933 tempcond = (num[0] <= num[1]);
2934 break;
2935
2936 case ECOND_STR_LT:
2937 tempcond = (Ustrcmp(sub[0], sub[1]) < 0);
2938 break;
2939
2940 case ECOND_STR_LTI:
2941 tempcond = (strcmpic(sub[0], sub[1]) < 0);
2942 break;
2943
2944 case ECOND_STR_LE:
2945 tempcond = (Ustrcmp(sub[0], sub[1]) <= 0);
2946 break;
2947
2948 case ECOND_STR_LEI:
2949 tempcond = (strcmpic(sub[0], sub[1]) <= 0);
2950 break;
2951
2952 case ECOND_STR_EQ:
2953 tempcond = (Ustrcmp(sub[0], sub[1]) == 0);
2954 break;
2955
2956 case ECOND_STR_EQI:
2957 tempcond = (strcmpic(sub[0], sub[1]) == 0);
2958 break;
2959
2960 case ECOND_STR_GT:
2961 tempcond = (Ustrcmp(sub[0], sub[1]) > 0);
2962 break;
2963
2964 case ECOND_STR_GTI:
2965 tempcond = (strcmpic(sub[0], sub[1]) > 0);
2966 break;
2967
2968 case ECOND_STR_GE:
2969 tempcond = (Ustrcmp(sub[0], sub[1]) >= 0);
2970 break;
2971
2972 case ECOND_STR_GEI:
2973 tempcond = (strcmpic(sub[0], sub[1]) >= 0);
2974 break;
2975
2976 case ECOND_MATCH: /* Regular expression match */
2977 if (!(re = pcre_compile(CS sub[1], PCRE_COPT, CCSS &rerror,
2978 &roffset, NULL)))
2979 {
2980 expand_string_message = string_sprintf("regular expression error in "
2981 "\"%s\": %s at offset %d", sub[1], rerror, roffset);
2982 return NULL;
2983 }
2984 tempcond = regex_match_and_setup(re, sub[0], 0, -1);
2985 break;
2986
2987 case ECOND_MATCH_ADDRESS: /* Match in an address list */
2988 rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0, NULL);
2989 goto MATCHED_SOMETHING;
2990
2991 case ECOND_MATCH_DOMAIN: /* Match in a domain list */
2992 rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
2993 MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
2994 goto MATCHED_SOMETHING;
2995
2996 case ECOND_MATCH_IP: /* Match IP address in a host list */
2997 if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) == 0)
2998 {
2999 expand_string_message = string_sprintf("\"%s\" is not an IP address",
3000 sub[0]);
3001 return NULL;
3002 }
3003 else
3004 {
3005 unsigned int *nullcache = NULL;
3006 check_host_block cb;
3007
3008 cb.host_name = US"";
3009 cb.host_address = sub[0];
3010
3011 /* If the host address starts off ::ffff: it is an IPv6 address in
3012 IPv4-compatible mode. Find the IPv4 part for checking against IPv4
3013 addresses. */
3014
3015 cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
3016 cb.host_address + 7 : cb.host_address;
3017
3018 rc = match_check_list(
3019 &sub[1], /* the list */
3020 0, /* separator character */
3021 &hostlist_anchor, /* anchor pointer */
3022 &nullcache, /* cache pointer */
3023 check_host, /* function for testing */
3024 &cb, /* argument for function */
3025 MCL_HOST, /* type of check */
3026 sub[0], /* text for debugging */
3027 NULL); /* where to pass back data */
3028 }
3029 goto MATCHED_SOMETHING;
3030
3031 case ECOND_MATCH_LOCAL_PART:
3032 rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
3033 MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
3034 /* Fall through */
3035 /* VVVVVVVVVVVV */
3036 MATCHED_SOMETHING:
3037 switch(rc)
3038 {
3039 case OK:
3040 tempcond = TRUE;
3041 break;
3042
3043 case FAIL:
3044 tempcond = FALSE;
3045 break;
3046
3047 case DEFER:
3048 expand_string_message = string_sprintf("unable to complete match "
3049 "against \"%s\": %s", sub[1], search_error_message);
3050 return NULL;
3051 }
3052
3053 break;
3054
3055 /* Various "encrypted" comparisons. If the second string starts with
3056 "{" then an encryption type is given. Default to crypt() or crypt16()
3057 (build-time choice). */
3058 /* }-for-text-editors */
3059
3060 case ECOND_CRYPTEQ:
3061 #ifndef SUPPORT_CRYPTEQ
3062 goto COND_FAILED_NOT_COMPILED;
3063 #else
3064 if (strncmpic(sub[1], US"{md5}", 5) == 0)
3065 {
3066 int sublen = Ustrlen(sub[1]+5);
3067 md5 base;
3068 uschar digest[16];
3069
3070 md5_start(&base);
3071 md5_end(&base, sub[0], Ustrlen(sub[0]), digest);
3072
3073 /* If the length that we are comparing against is 24, the MD5 digest
3074 is expressed as a base64 string. This is the way LDAP does it. However,
3075 some other software uses a straightforward hex representation. We assume
3076 this if the length is 32. Other lengths fail. */
3077
3078 if (sublen == 24)
3079 {
3080 uschar *coded = b64encode(CUS digest, 16);
3081 DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
3082 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
3083 tempcond = (Ustrcmp(coded, sub[1]+5) == 0);
3084 }
3085 else if (sublen == 32)
3086 {
3087 uschar coded[36];
3088 for (int i = 0; i < 16; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3089 coded[32] = 0;
3090 DEBUG(D_auth) debug_printf("crypteq: using MD5+hex hashing\n"
3091 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
3092 tempcond = (strcmpic(coded, sub[1]+5) == 0);
3093 }
3094 else
3095 {
3096 DEBUG(D_auth) debug_printf("crypteq: length for MD5 not 24 or 32: "
3097 "fail\n crypted=%s\n", sub[1]+5);
3098 tempcond = FALSE;
3099 }
3100 }
3101
3102 else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
3103 {
3104 int sublen = Ustrlen(sub[1]+6);
3105 hctx h;
3106 uschar digest[20];
3107
3108 sha1_start(&h);
3109 sha1_end(&h, sub[0], Ustrlen(sub[0]), digest);
3110
3111 /* If the length that we are comparing against is 28, assume the SHA1
3112 digest is expressed as a base64 string. If the length is 40, assume a
3113 straightforward hex representation. Other lengths fail. */
3114
3115 if (sublen == 28)
3116 {
3117 uschar *coded = b64encode(CUS digest, 20);
3118 DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
3119 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
3120 tempcond = (Ustrcmp(coded, sub[1]+6) == 0);
3121 }
3122 else if (sublen == 40)
3123 {
3124 uschar coded[44];
3125 for (int i = 0; i < 20; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
3126 coded[40] = 0;
3127 DEBUG(D_auth) debug_printf("crypteq: using SHA1+hex hashing\n"
3128 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
3129 tempcond = (strcmpic(coded, sub[1]+6) == 0);
3130 }
3131 else
3132 {
3133 DEBUG(D_auth) debug_printf("crypteq: length for SHA-1 not 28 or 40: "
3134 "fail\n crypted=%s\n", sub[1]+6);
3135 tempcond = FALSE;
3136 }
3137 }
3138
3139 else /* {crypt} or {crypt16} and non-{ at start */
3140 /* }-for-text-editors */
3141 {
3142 int which = 0;
3143 uschar *coded;
3144
3145 if (strncmpic(sub[1], US"{crypt}", 7) == 0)
3146 {
3147 sub[1] += 7;
3148 which = 1;
3149 }
3150 else if (strncmpic(sub[1], US"{crypt16}", 9) == 0)
3151 {
3152 sub[1] += 9;
3153 which = 2;
3154 }
3155 else if (sub[1][0] == '{') /* }-for-text-editors */
3156 {
3157 expand_string_message = string_sprintf("unknown encryption mechanism "
3158 "in \"%s\"", sub[1]);
3159 return NULL;
3160 }
3161
3162 switch(which)
3163 {
3164 case 0: coded = US DEFAULT_CRYPT(CS sub[0], CS sub[1]); break;
3165 case 1: coded = US crypt(CS sub[0], CS sub[1]); break;
3166 default: coded = US crypt16(CS sub[0], CS sub[1]); break;
3167 }
3168
3169 #define STR(s) # s
3170 #define XSTR(s) STR(s)
3171 DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
3172 " subject=%s\n crypted=%s\n",
3173 which == 0 ? XSTR(DEFAULT_CRYPT) : which == 1 ? "crypt" : "crypt16",
3174 coded, sub[1]);
3175 #undef STR
3176 #undef XSTR
3177
3178 /* If the encrypted string contains fewer than two characters (for the
3179 salt), force failure. Otherwise we get false positives: with an empty
3180 string the yield of crypt() is an empty string! */
3181
3182 if (coded)
3183 tempcond = Ustrlen(sub[1]) < 2 ? FALSE : Ustrcmp(coded, sub[1]) == 0;
3184 else if (errno == EINVAL)
3185 tempcond = FALSE;
3186 else
3187 {
3188 expand_string_message = string_sprintf("crypt error: %s\n",
3189 US strerror(errno));
3190 return NULL;
3191 }
3192 }
3193 break;
3194 #endif /* SUPPORT_CRYPTEQ */
3195
3196 case ECOND_INLIST:
3197 case ECOND_INLISTI:
3198 {
3199 const uschar * list = sub[1];
3200 int sep = 0;
3201 uschar *save_iterate_item = iterate_item;
3202 int (*compare)(const uschar *, const uschar *);
3203
3204 DEBUG(D_expand) debug_printf_indent("condition: %s item: %s\n", opname, sub[0]);
3205
3206 tempcond = FALSE;
3207 compare = cond_type == ECOND_INLISTI
3208 ? strcmpic : (int (*)(const uschar *, const uschar *)) strcmp;
3209
3210 while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
3211 {
3212 DEBUG(D_expand) debug_printf_indent(" compare %s\n", iterate_item);
3213 if (compare(sub[0], iterate_item) == 0)
3214 {
3215 tempcond = TRUE;
3216 break;
3217 }
3218 }
3219 iterate_item = save_iterate_item;
3220 }
3221
3222 } /* Switch for comparison conditions */
3223
3224 *yield = tempcond == testfor;
3225 return s; /* End of comparison conditions */
3226
3227
3228 /* and/or: computes logical and/or of several conditions */
3229
3230 case ECOND_AND:
3231 case ECOND_OR:
3232 subcondptr = (yield == NULL) ? NULL : &tempcond;
3233 combined_cond = (cond_type == ECOND_AND);
3234
3235 Uskip_whitespace(&s);
3236 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3237
3238 for (;;)
3239 {
3240 /* {-for-text-editors */
3241 if (Uskip_whitespace(&s) == '}') break;
3242 if (*s != '{') /* }-for-text-editors */
3243 {
3244 expand_string_message = string_sprintf("each subcondition "
3245 "inside an \"%s{...}\" condition must be in its own {}", opname);
3246 return NULL;
3247 }
3248
3249 if (!(s = eval_condition(s+1, resetok, subcondptr)))
3250 {
3251 expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
3252 expand_string_message, opname);
3253 return NULL;
3254 }
3255 Uskip_whitespace(&s);
3256
3257 /* {-for-text-editors */
3258 if (*s++ != '}')
3259 {
3260 /* {-for-text-editors */
3261 expand_string_message = string_sprintf("missing } at end of condition "
3262 "inside \"%s\" group", opname);
3263 return NULL;
3264 }
3265
3266 if (yield)
3267 if (cond_type == ECOND_AND)
3268 {
3269 combined_cond &= tempcond;
3270 if (!combined_cond) subcondptr = NULL; /* once false, don't */
3271 } /* evaluate any more */
3272 else
3273 {
3274 combined_cond |= tempcond;
3275 if (combined_cond) subcondptr = NULL; /* once true, don't */
3276 } /* evaluate any more */
3277 }
3278
3279 if (yield) *yield = (combined_cond == testfor);
3280 return ++s;
3281
3282
3283 /* forall/forany: iterates a condition with different values */
3284
3285 case ECOND_FORALL: is_forany = FALSE; is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3286 case ECOND_FORANY: is_forany = TRUE; is_json = FALSE; is_jsons = FALSE; goto FORMANY;
3287 case ECOND_FORALL_JSON: is_forany = FALSE; is_json = TRUE; is_jsons = FALSE; goto FORMANY;
3288 case ECOND_FORANY_JSON: is_forany = TRUE; is_json = TRUE; is_jsons = FALSE; goto FORMANY;
3289 case ECOND_FORALL_JSONS: is_forany = FALSE; is_json = TRUE; is_jsons = TRUE; goto FORMANY;
3290 case ECOND_FORANY_JSONS: is_forany = TRUE; is_json = TRUE; is_jsons = TRUE; goto FORMANY;
3291
3292 FORMANY:
3293 {
3294 const uschar * list;
3295 int sep = 0;
3296 uschar *save_iterate_item = iterate_item;
3297
3298 DEBUG(D_expand) debug_printf_indent("condition: %s\n", opname);
3299
3300 Uskip_whitespace(&s);
3301 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3302 if (!(sub[0] = expand_string_internal(s, TRUE, &s, yield == NULL, TRUE, resetok)))
3303 return NULL;
3304 /* {-for-text-editors */
3305 if (*s++ != '}') goto COND_FAILED_CURLY_END;
3306
3307 Uskip_whitespace(&s);
3308 if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3309
3310 sub[1] = s;
3311
3312 /* Call eval_condition once, with result discarded (as if scanning a
3313 "false" part). This allows us to find the end of the condition, because if
3314 the list it empty, we won't actually evaluate the condition for real. */
3315
3316 if (!(s = eval_condition(sub[1], resetok, NULL)))
3317 {
3318 expand_string_message = string_sprintf("%s inside \"%s\" condition",
3319 expand_string_message, opname);
3320 return NULL;
3321 }
3322 Uskip_whitespace(&s);
3323
3324 /* {-for-text-editors */
3325 if (*s++ != '}')
3326 {
3327 /* {-for-text-editors */
3328 expand_string_message = string_sprintf("missing } at end of condition "
3329 "inside \"%s\"", opname);
3330 return NULL;
3331 }
3332
3333 if (yield) *yield = !testfor;
3334 list = sub[0];
3335 if (is_json) list = dewrap(string_copy(list), US"[]");
3336 while ((iterate_item = is_json
3337 ? json_nextinlist(&list) : string_nextinlist(&list, &sep, NULL, 0)))
3338 {
3339 if (is_jsons)
3340 if (!(iterate_item = dewrap(iterate_item, US"\"\"")))
3341 {
3342 expand_string_message =
3343 string_sprintf("%s wrapping string result for extract jsons",
3344 expand_string_message);
3345 iterate_item = save_iterate_item;
3346 return NULL;
3347 }
3348
3349 DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", opname, iterate_item);
3350 if (!eval_condition(sub[1], resetok, &tempcond))
3351 {
3352 expand_string_message = string_sprintf("%s inside \"%s\" condition",
3353 expand_string_message, opname);
3354 iterate_item = save_iterate_item;
3355 return NULL;
3356 }
3357 DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", opname,
3358 tempcond? "true":"false");
3359
3360 if (yield) *yield = (tempcond == testfor);
3361 if (tempcond == is_forany) break;
3362 }
3363
3364 iterate_item = save_iterate_item;
3365 return s;
3366 }
3367
3368
3369 /* The bool{} expansion condition maps a string to boolean.
3370 The values supported should match those supported by the ACL condition
3371 (acl.c, ACLC_CONDITION) so that we keep to a minimum the different ideas
3372 of true/false. Note that Router "condition" rules have a different
3373 interpretation, where general data can be used and only a few values
3374 map to FALSE.
3375 Note that readconf.c boolean matching, for boolean configuration options,
3376 only matches true/yes/false/no.
3377 The bool_lax{} condition matches the Router logic, which is much more
3378 liberal. */
3379 case ECOND_BOOL:
3380 case ECOND_BOOL_LAX:
3381 {
3382 uschar *sub_arg[1];
3383 uschar *t, *t2;
3384 uschar *ourname;
3385 size_t len;
3386 BOOL boolvalue = FALSE;
3387
3388 if (Uskip_whitespace(&s) != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
3389 ourname = cond_type == ECOND_BOOL_LAX ? US"bool_lax" : US"bool";
3390 switch(read_subs(sub_arg, 1, 1, &s, yield == NULL, FALSE, ourname, resetok))
3391 {
3392 case 1: expand_string_message = string_sprintf(
3393 "too few arguments or bracketing error for %s",
3394 ourname);
3395 /*FALLTHROUGH*/
3396 case 2:
3397 case 3: return NULL;
3398 }
3399 t = sub_arg[0];
3400 Uskip_whitespace(&t);
3401 if ((len = Ustrlen(t)))
3402 {
3403 /* trailing whitespace: seems like a good idea to ignore it too */
3404 t2 = t + len - 1;
3405 while (isspace(*t2)) t2--;
3406 if (t2 != (t + len))
3407 {
3408 *++t2 = '\0';
3409 len = t2 - t;
3410 }
3411 }
3412 DEBUG(D_expand)
3413 debug_printf_indent("considering %s: %s\n", ourname, len ? t : US"<empty>");
3414 /* logic for the lax case from expand_check_condition(), which also does
3415 expands, and the logic is both short and stable enough that there should
3416 be no maintenance burden from replicating it. */
3417 if (len == 0)
3418 boolvalue = FALSE;
3419 else if (*t == '-'
3420 ? Ustrspn(t+1, "0123456789") == len-1
3421 : Ustrspn(t, "0123456789") == len)
3422 {
3423 boolvalue = (Uatoi(t) == 0) ? FALSE : TRUE;
3424 /* expand_check_condition only does a literal string "0" check */
3425 if ((cond_type == ECOND_BOOL_LAX) && (len > 1))
3426 boolvalue = TRUE;
3427 }
3428 else if (strcmpic(t, US"true") == 0 || strcmpic(t, US"yes") == 0)
3429 boolvalue = TRUE;
3430 else if (strcmpic(t, US"false") == 0 || strcmpic(t, US"no") == 0)
3431 boolvalue = FALSE;
3432 else if (cond_type == ECOND_BOOL_LAX)
3433 boolvalue = TRUE;
3434 else
3435 {
3436 expand_string_message = string_sprintf("unrecognised boolean "
3437 "value \"%s\"", t);
3438 return NULL;
3439 }
3440 DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", ourname,
3441 boolvalue? "true":"false");
3442 if (yield) *yield = (boolvalue == testfor);
3443 return s;
3444 }
3445
3446 #ifdef EXPERIMENTAL_SRS_NATIVE
3447 case ECOND_INBOUND_SRS:
3448 /* ${if inbound_srs {local_part}{secret} {yes}{no}} */
3449 {
3450 uschar * sub[2];
3451 const pcre * re;
3452 int ovec[3*(4+1)];
3453 int n;
3454 uschar cksum[4];
3455 BOOL boolvalue = FALSE;
3456
3457 switch(read_subs(sub, 2, 2, CUSS &s, yield == NULL, FALSE, name, resetok))
3458 {
3459 case 1: expand_string_message = US"too few arguments or bracketing "
3460 "error for inbound_srs";
3461 case 2:
3462 case 3: return NULL;
3463 }
3464
3465 /* Match the given local_part against the SRS-encoded pattern */
3466
3467 re = regex_must_compile(US"^(?i)SRS0=([^=]+)=([A-Z2-7]+)=([^=]*)=(.*)$",
3468 TRUE, FALSE);
3469 if (pcre_exec(re, NULL, CS sub[0], Ustrlen(sub[0]), 0, PCRE_EOPT,
3470 ovec, nelem(ovec)) < 0)
3471 {
3472 DEBUG(D_expand) debug_printf("no match for SRS'd local-part pattern\n");
3473 goto srs_result;
3474 }
3475
3476 /* Side-effect: record the decoded recipient */
3477
3478 srs_recipient = string_sprintf("%.*S@%.*S", /* lowercased */
3479 ovec[9]-ovec[8], sub[0] + ovec[8], /* substring 4 */
3480 ovec[7]-ovec[6], sub[0] + ovec[6]); /* substring 3 */
3481
3482 /* If a zero-length secret was given, we're done. Otherwise carry on
3483 and validate the given SRS local_part againt our secret. */
3484
3485 if (!*sub[1])
3486 {
3487 boolvalue = TRUE;
3488 goto srs_result;
3489 }
3490
3491 /* check the timestamp */
3492 {
3493 struct timeval now;
3494 uschar * ss = sub[0] + ovec[4]; /* substring 2, the timestamp */
3495 long d;
3496
3497 gettimeofday(&now, NULL);
3498 now.tv_sec /= 86400; /* days since epoch */
3499
3500 /* Decode substring 2 from base32 to a number */
3501
3502 for (d = 0, n = ovec[5]-ovec[4]; n; n--)
3503 {
3504 uschar * t = Ustrchr(base32_chars, *ss++);
3505 d = d * 32 + (t - base32_chars);
3506 }
3507
3508 if (((now.tv_sec - d) & 0x3ff) > 10) /* days since SRS generated */
3509 {
3510 DEBUG(D_expand) debug_printf("SRS too old\n");
3511 goto srs_result;
3512 }
3513 }
3514
3515 /* check length of substring 1, the offered checksum */
3516
3517 if (ovec[3]-ovec[2] != 4)
3518 {
3519 DEBUG(D_expand) debug_printf("SRS checksum wrong size\n");
3520 goto srs_result;
3521 }
3522
3523 /* Hash the address with our secret, and compare that computed checksum
3524 with the one extracted from the arg */
3525
3526 hmac_md5(sub[1], srs_recipient, cksum, sizeof(cksum));
3527 if (Ustrncmp(cksum, sub[0] + ovec[2], 4) != 0)
3528 {
3529 DEBUG(D_expand) debug_printf("SRS checksum mismatch\n");
3530 goto srs_result;
3531 }
3532 boolvalue = TRUE;
3533
3534 srs_result:
3535 if (yield) *yield = (boolvalue == testfor);
3536 return s;
3537 }
3538 #endif /*EXPERIMENTAL_SRS_NATIVE*/
3539
3540 /* Unknown condition */
3541
3542 default:
3543 if (!expand_string_message || !*expand_string_message)
3544 expand_string_message = string_sprintf("unknown condition \"%s\"", opname);
3545 return NULL;
3546 } /* End switch on condition type */
3547
3548 /* Missing braces at start and end of data */
3549
3550 COND_FAILED_CURLY_START:
3551 expand_string_message = string_sprintf("missing { after \"%s\"", opname);
3552 return NULL;
3553
3554 COND_FAILED_CURLY_END:
3555 expand_string_message = string_sprintf("missing } at end of \"%s\" condition",
3556 opname);
3557 return NULL;
3558
3559 /* A condition requires code that is not compiled */
3560
3561 #if !defined(SUPPORT_PAM) || !defined(RADIUS_CONFIG_FILE) || \
3562 !defined(LOOKUP_LDAP) || !defined(CYRUS_PWCHECK_SOCKET) || \
3563 !defined(SUPPORT_CRYPTEQ) || !defined(CYRUS_SASLAUTHD_SOCKET)
3564 COND_FAILED_NOT_COMPILED:
3565 expand_string_message = string_sprintf("support for \"%s\" not compiled",
3566 opname);
3567 return NULL;
3568 #endif
3569 }
3570
3571
3572
3573
3574 /*************************************************
3575 * Save numerical variables *
3576 *************************************************/
3577
3578 /* This function is called from items such as "if" that want to preserve and
3579 restore the numbered variables.
3580
3581 Arguments:
3582 save_expand_string points to an array of pointers to set
3583 save_expand_nlength points to an array of ints for the lengths
3584
3585 Returns: the value of expand max to save
3586 */
3587
3588 static int
3589 save_expand_strings(uschar **save_expand_nstring, int *save_expand_nlength)
3590 {
3591 for (int i = 0; i <= expand_nmax; i++)
3592 {
3593 save_expand_nstring[i] = expand_nstring[i];
3594 save_expand_nlength[i] = expand_nlength[i];
3595 }
3596 return expand_nmax;
3597 }
3598
3599
3600
3601 /*************************************************
3602 * Restore numerical variables *
3603 *************************************************/
3604
3605 /* This function restored saved values of numerical strings.
3606
3607 Arguments:
3608 save_expand_nmax the number of strings to restore
3609 save_expand_string points to an array of pointers
3610 save_expand_nlength points to an array of ints
3611
3612 Returns: nothing
3613 */
3614
3615 static void
3616 restore_expand_strings(int save_expand_nmax, uschar **save_expand_nstring,
3617 int *save_expand_nlength)
3618 {
3619 expand_nmax = save_expand_nmax;
3620 for (int i = 0; i <= expand_nmax; i++)
3621 {
3622 expand_nstring[i] = save_expand_nstring[i];
3623 expand_nlength[i] = save_expand_nlength[i];
3624 }
3625 }
3626
3627
3628
3629
3630
3631 /*************************************************
3632 * Handle yes/no substrings *
3633 *************************************************/
3634
3635 /* This function is used by ${if}, ${lookup} and ${extract} to handle the
3636 alternative substrings that depend on whether or not the condition was true,
3637 or the lookup or extraction succeeded. The substrings always have to be
3638 expanded, to check their syntax, but "skipping" is set when the result is not
3639 needed - this avoids unnecessary nested lookups.
3640
3641 Arguments:
3642 skipping TRUE if we were skipping when this item was reached
3643 yes TRUE if the first string is to be used, else use the second
3644 save_lookup a value to put back into lookup_value before the 2nd expansion
3645 sptr points to the input string pointer
3646 yieldptr points to the output growable-string pointer
3647 type "lookup", "if", "extract", "run", "env", "listextract" or
3648 "certextract" for error message
3649 resetok if not NULL, pointer to flag - write FALSE if unsafe to reset
3650 the store.
3651
3652 Returns: 0 OK; lookup_value has been reset to save_lookup
3653 1 expansion failed
3654 2 expansion failed because of bracketing error
3655 */
3656
3657 static int
3658 process_yesno(BOOL skipping, BOOL yes, uschar *save_lookup, const uschar **sptr,
3659 gstring ** yieldptr, uschar *type, BOOL *resetok)
3660 {
3661 int rc = 0;
3662 const uschar *s = *sptr; /* Local value */
3663 uschar *sub1, *sub2;
3664 const uschar * errwhere;
3665
3666 /* If there are no following strings, we substitute the contents of $value for
3667 lookups and for extractions in the success case. For the ${if item, the string
3668 "true" is substituted. In the fail case, nothing is substituted for all three
3669 items. */
3670
3671 if (skip_whitespace(&s) == '}')
3672 {
3673 if (type[0] == 'i')
3674 {
3675 if (yes && !skipping)
3676 *yieldptr = string_catn(*yieldptr, US"true", 4);
3677 }
3678 else
3679 {
3680 if (yes && lookup_value && !skipping)
3681 *yieldptr = string_cat(*yieldptr, lookup_value);
3682 lookup_value = save_lookup;
3683 }
3684 s++;
3685 goto RETURN;
3686 }
3687
3688 /* The first following string must be braced. */
3689
3690 if (*s++ != '{')
3691 {
3692 errwhere = US"'yes' part did not start with '{'";
3693 goto FAILED_CURLY;
3694 }
3695
3696 /* Expand the first substring. Forced failures are noticed only if we actually
3697 want this string. Set skipping in the call in the fail case (this will always
3698 be the case if we were already skipping). */
3699
3700 sub1 = expand_string_internal(s, TRUE, &s, !yes, TRUE, resetok);
3701 if (sub1 == NULL && (yes || !f.expand_string_forcedfail)) goto FAILED;
3702 f.expand_string_forcedfail = FALSE;
3703 if (*s++ != '}')
3704 {
3705 errwhere = US"'yes' part did not end with '}'";
3706 goto FAILED_CURLY;
3707 }
3708
3709 /* If we want the first string, add it to the output */
3710
3711 if (yes)
3712 *yieldptr = string_cat(*yieldptr, sub1);
3713
3714 /* If this is called from a lookup/env or a (cert)extract, we want to restore
3715 $value to what it was at the start of the item, so that it has this value
3716 during the second string expansion. For the call from "if" or "run" to this
3717 function, save_lookup is set to lookup_value, so that this statement does
3718 nothing. */
3719
3720 lookup_value = save_lookup;
3721
3722 /* There now follows either another substring, or "fail", or nothing. This
3723 time, forced failures are noticed only if we want the second string. We must
3724 set skipping in the nested call if we don't want this string, or if we were
3725 already skipping. */
3726
3727 if (skip_whitespace(&s) == '{')
3728 {
3729 sub2 = expand_string_internal(s+1, TRUE, &s, yes || skipping, TRUE, resetok);
3730 if (sub2 == NULL && (!yes || !f.expand_string_forcedfail)) goto FAILED;
3731 f.expand_string_forcedfail = FALSE;
3732 if (*s++ != '}')
3733 {
3734 errwhere = US"'no' part did not start with '{'";
3735 goto FAILED_CURLY;
3736 }
3737
3738 /* If we want the second string, add it to the output */
3739
3740 if (!yes)
3741 *yieldptr = string_cat(*yieldptr, sub2);
3742 }
3743
3744 /* If there is no second string, but the word "fail" is present when the use of
3745 the second string is wanted, set a flag indicating it was a forced failure
3746 rather than a syntactic error. Swallow the terminating } in case this is nested
3747 inside another lookup or if or extract. */
3748
3749 else if (*s != '}')
3750 {
3751 uschar name[256];
3752 /* deconst cast ok here as source is s anyway */
3753 s = US read_name(name, sizeof(name), s, US"_");
3754 if (Ustrcmp(name, "fail") == 0)
3755 {
3756 if (!yes && !skipping)
3757 {
3758 Uskip_whitespace(&s);
3759 if (*s++ != '}')
3760 {
3761 errwhere = US"did not close with '}' after forcedfail";
3762 goto FAILED_CURLY;
3763 }
3764 expand_string_message =
3765 string_sprintf("\"%s\" failed and \"fail\" requested", type);
3766 f.expand_string_forcedfail = TRUE;
3767 goto FAILED;
3768 }
3769 }
3770 else
3771 {
3772 expand_string_message =
3773 string_sprintf("syntax error in \"%s\" item - \"fail\" expected", type);
3774 goto FAILED;
3775 }
3776 }
3777
3778 /* All we have to do now is to check on the final closing brace. */
3779
3780 skip_whitespace(&s);
3781 if (*s++ != '}')
3782 {
3783 errwhere = US"did not close with '}'";
3784 goto FAILED_CURLY;
3785 }
3786
3787
3788 RETURN:
3789 /* Update the input pointer value before returning */
3790 *sptr = s;
3791 return rc;
3792
3793 FAILED_CURLY:
3794 /* Get here if there is a bracketing failure */
3795 expand_string_message = string_sprintf(
3796 "curly-bracket problem in conditional yes/no parsing: %s\n"
3797 " remaining string is '%s'", errwhere, --s);
3798 rc = 2;
3799 goto RETURN;
3800
3801 FAILED:
3802 /* Get here for other failures */
3803 rc = 1;
3804 goto RETURN;
3805 }
3806
3807
3808
3809
3810 /********************************************************
3811 * prvs: Get last three digits of days since Jan 1, 1970 *
3812 ********************************************************/
3813
3814 /* This is needed to implement the "prvs" BATV reverse
3815 path signing scheme
3816
3817 Argument: integer "days" offset to add or substract to
3818 or from the current number of days.
3819
3820 Returns: pointer to string containing the last three
3821 digits of the number of days since Jan 1, 1970,
3822 modified by the offset argument, NULL if there
3823 was an error in the conversion.
3824
3825 */
3826
3827 static uschar *
3828 prvs_daystamp(int day_offset)
3829 {
3830 uschar *days = store_get(32, FALSE); /* Need at least 24 for cases */
3831 (void)string_format(days, 32, TIME_T_FMT, /* where TIME_T_FMT is %lld */
3832 (time(NULL) + day_offset*86400)/86400);
3833 return (Ustrlen(days) >= 3) ? &days[Ustrlen(days)-3] : US"100";
3834 }
3835
3836
3837
3838 /********************************************************
3839 * prvs: perform HMAC-SHA1 computation of prvs bits *
3840 ********************************************************/
3841
3842 /* This is needed to implement the "prvs" BATV reverse
3843 path signing scheme
3844
3845 Arguments:
3846 address RFC2821 Address to use
3847 key The key to use (must be less than 64 characters
3848 in size)
3849 key_num Single-digit key number to use. Defaults to
3850 '0' when NULL.
3851
3852 Returns: pointer to string containing the first three
3853 bytes of the final hash in hex format, NULL if
3854 there was an error in the process.
3855 */
3856
3857 static uschar *
3858 prvs_hmac_sha1(uschar *address, uschar *key, uschar *key_num, uschar *daystamp)
3859 {
3860 gstring * hash_source;
3861 uschar * p;
3862 hctx h;
3863 uschar innerhash[20];
3864 uschar finalhash[20];
3865 uschar innerkey[64];
3866 uschar outerkey[64];
3867 uschar *finalhash_hex;
3868
3869 if (!key_num)
3870 key_num = US"0";
3871
3872 if (Ustrlen(key) > 64)
3873 return NULL;
3874
3875 hash_source = string_catn(NULL, key_num, 1);
3876 hash_source = string_catn(hash_source, daystamp, 3);
3877 hash_source = string_cat(hash_source, address);
3878 (void) string_from_gstring(hash_source);
3879
3880 DEBUG(D_expand)
3881 debug_printf_indent("prvs: hash source is '%s'\n", hash_source->s);
3882
3883 memset(innerkey, 0x36, 64);
3884 memset(outerkey, 0x5c, 64);
3885
3886 for (int i = 0; i < Ustrlen(key); i++)
3887 {
3888 innerkey[i] ^= key[i];
3889 outerkey[i] ^= key[i];
3890 }
3891
3892 chash_start(HMAC_SHA1, &h);
3893 chash_mid(HMAC_SHA1, &h, innerkey);
3894 chash_end(HMAC_SHA1, &h, hash_source->s, hash_source->ptr, innerhash);
3895
3896 chash_start(HMAC_SHA1, &h);
3897 chash_mid(HMAC_SHA1, &h, outerkey);
3898 chash_end(HMAC_SHA1, &h, innerhash, 20, finalhash);
3899
3900 /* Hashing is deemed sufficient to de-taint any input data */
3901
3902 p = finalhash_hex = store_get(40, FALSE);
3903 for (int i = 0; i < 3; i++)
3904 {
3905 *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
3906 *p++ = hex_digits[finalhash[i] & 0x0f];
3907 }
3908 *p = '\0';
3909
3910 return finalhash_hex;
3911 }
3912
3913
3914
3915
3916 /*************************************************
3917 * Join a file onto the output string *
3918 *************************************************/
3919
3920 /* This is used for readfile/readsock and after a run expansion.
3921 It joins the contents of a file onto the output string, globally replacing
3922 newlines with a given string (optionally).
3923
3924 Arguments:
3925 f the FILE
3926 yield pointer to the expandable string struct
3927 eol newline replacement string, or NULL
3928