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