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