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