Apply Jakob Hirsch's patch for arbitrary ACL variable names, tidied up
[exim.git] / src / src / expand.c
CommitLineData
38a0a95f 1/* $Cambridge: exim/src/src/expand.c,v 1.61 2006/09/19 11:28:45 ph10 Exp $ */
059ec3d9
PH
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
d7d7b7b9 7/* Copyright (c) University of Cambridge 1995 - 2006 */
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
16#ifdef STAND_ALONE
17#ifndef SUPPORT_CRYPTEQ
18#define SUPPORT_CRYPTEQ
19#endif
20#endif
21
22#ifdef SUPPORT_CRYPTEQ
23#ifdef CRYPT_H
24#include <crypt.h>
25#endif
26#ifndef HAVE_CRYPT16
27extern char* crypt16(char*, char*);
28#endif
29#endif
30
31#ifdef LOOKUP_LDAP
32#include "lookups/ldap.h"
33#endif
34
35
36
37/* Recursively called function */
38
39static uschar *expand_string_internal(uschar *, BOOL, uschar **, BOOL);
40
41
42
43/*************************************************
44* Local statics and tables *
45*************************************************/
46
47/* Table of item names, and corresponding switch numbers. The names must be in
48alphabetical order. */
49
50static uschar *item_table[] = {
1a46a8c5 51 US"dlfunc",
059ec3d9
PH
52 US"extract",
53 US"hash",
54 US"hmac",
55 US"if",
56 US"length",
57 US"lookup",
58 US"nhash",
1a46a8c5 59 US"perl",
fffda43a
TK
60 US"prvs",
61 US"prvscheck",
059ec3d9
PH
62 US"readfile",
63 US"readsocket",
64 US"run",
65 US"sg",
66 US"substr",
67 US"tr" };
68
69enum {
1a46a8c5 70 EITEM_DLFUNC,
059ec3d9
PH
71 EITEM_EXTRACT,
72 EITEM_HASH,
73 EITEM_HMAC,
74 EITEM_IF,
75 EITEM_LENGTH,
76 EITEM_LOOKUP,
77 EITEM_NHASH,
1a46a8c5 78 EITEM_PERL,
fffda43a
TK
79 EITEM_PRVS,
80 EITEM_PRVSCHECK,
059ec3d9
PH
81 EITEM_READFILE,
82 EITEM_READSOCK,
83 EITEM_RUN,
84 EITEM_SG,
85 EITEM_SUBSTR,
86 EITEM_TR };
87
88/* Tables of operator names, and corresponding switch numbers. The names must be
89in alphabetical order. There are two tables, because underscore is used in some
90cases to introduce arguments, whereas for other it is part of the name. This is
91an historical mis-design. */
92
93static uschar *op_table_underscore[] = {
94 US"from_utf8",
95 US"local_part",
96 US"quote_local_part",
f90d018c 97 US"time_eval",
059ec3d9
PH
98 US"time_interval"};
99
100enum {
101 EOP_FROM_UTF8,
102 EOP_LOCAL_PART,
103 EOP_QUOTE_LOCAL_PART,
f90d018c 104 EOP_TIME_EVAL,
059ec3d9
PH
105 EOP_TIME_INTERVAL };
106
107static uschar *op_table_main[] = {
108 US"address",
109 US"base62",
110 US"base62d",
111 US"domain",
112 US"escape",
113 US"eval",
114 US"eval10",
115 US"expand",
116 US"h",
117 US"hash",
118 US"hex2b64",
119 US"l",
120 US"lc",
121 US"length",
122 US"mask",
123 US"md5",
124 US"nh",
125 US"nhash",
126 US"quote",
127 US"rfc2047",
128 US"rxquote",
129 US"s",
130 US"sha1",
131 US"stat",
132 US"str2b64",
133 US"strlen",
134 US"substr",
135 US"uc" };
136
137enum {
138 EOP_ADDRESS = sizeof(op_table_underscore)/sizeof(uschar *),
139 EOP_BASE62,
140 EOP_BASE62D,
141 EOP_DOMAIN,
142 EOP_ESCAPE,
143 EOP_EVAL,
144 EOP_EVAL10,
145 EOP_EXPAND,
146 EOP_H,
147 EOP_HASH,
148 EOP_HEX2B64,
149 EOP_L,
150 EOP_LC,
151 EOP_LENGTH,
152 EOP_MASK,
153 EOP_MD5,
154 EOP_NH,
155 EOP_NHASH,
156 EOP_QUOTE,
157 EOP_RFC2047,
158 EOP_RXQUOTE,
159 EOP_S,
160 EOP_SHA1,
161 EOP_STAT,
162 EOP_STR2B64,
163 EOP_STRLEN,
164 EOP_SUBSTR,
165 EOP_UC };
166
167
168/* Table of condition names, and corresponding switch numbers. The names must
169be in alphabetical order. */
170
171static uschar *cond_table[] = {
172 US"<",
173 US"<=",
174 US"=",
175 US"==", /* Backward compatibility */
176 US">",
177 US">=",
178 US"and",
179 US"crypteq",
180 US"def",
181 US"eq",
182 US"eqi",
183 US"exists",
184 US"first_delivery",
185 US"ge",
186 US"gei",
187 US"gt",
188 US"gti",
189 US"isip",
190 US"isip4",
191 US"isip6",
192 US"ldapauth",
193 US"le",
194 US"lei",
195 US"lt",
196 US"lti",
197 US"match",
198 US"match_address",
199 US"match_domain",
32d668a5 200 US"match_ip",
059ec3d9
PH
201 US"match_local_part",
202 US"or",
203 US"pam",
204 US"pwcheck",
205 US"queue_running",
206 US"radius",
207 US"saslauthd"
208};
209
210enum {
211 ECOND_NUM_L,
212 ECOND_NUM_LE,
213 ECOND_NUM_E,
214 ECOND_NUM_EE,
215 ECOND_NUM_G,
216 ECOND_NUM_GE,
217 ECOND_AND,
218 ECOND_CRYPTEQ,
219 ECOND_DEF,
220 ECOND_STR_EQ,
221 ECOND_STR_EQI,
222 ECOND_EXISTS,
223 ECOND_FIRST_DELIVERY,
224 ECOND_STR_GE,
225 ECOND_STR_GEI,
226 ECOND_STR_GT,
227 ECOND_STR_GTI,
228 ECOND_ISIP,
229 ECOND_ISIP4,
230 ECOND_ISIP6,
231 ECOND_LDAPAUTH,
232 ECOND_STR_LE,
233 ECOND_STR_LEI,
234 ECOND_STR_LT,
235 ECOND_STR_LTI,
236 ECOND_MATCH,
237 ECOND_MATCH_ADDRESS,
238 ECOND_MATCH_DOMAIN,
32d668a5 239 ECOND_MATCH_IP,
059ec3d9
PH
240 ECOND_MATCH_LOCAL_PART,
241 ECOND_OR,
242 ECOND_PAM,
243 ECOND_PWCHECK,
244 ECOND_QUEUE_RUNNING,
245 ECOND_RADIUS,
246 ECOND_SASLAUTHD
247};
248
249
250/* Type for main variable table */
251
252typedef struct {
253 char *name;
254 int type;
255 void *value;
256} var_entry;
257
258/* Type for entries pointing to address/length pairs. Not currently
259in use. */
260
261typedef struct {
262 uschar **address;
263 int *length;
264} alblock;
265
266/* Types of table entry */
267
268enum {
269 vtype_int, /* value is address of int */
270 vtype_filter_int, /* ditto, but recognized only when filtering */
271 vtype_ino, /* value is address of ino_t (not always an int) */
272 vtype_uid, /* value is address of uid_t (not always an int) */
273 vtype_gid, /* value is address of gid_t (not always an int) */
274 vtype_stringptr, /* value is address of pointer to string */
275 vtype_msgbody, /* as stringptr, but read when first required */
276 vtype_msgbody_end, /* ditto, the end of the message */
277 vtype_msgheaders, /* the message's headers */
278 vtype_localpart, /* extract local part from string */
279 vtype_domain, /* extract domain from string */
280 vtype_recipients, /* extract recipients from recipients list */
281 /* (enabled only during system filtering */
282 vtype_todbsdin, /* value not used; generate BSD inbox tod */
283 vtype_tode, /* value not used; generate tod in epoch format */
284 vtype_todf, /* value not used; generate full tod */
285 vtype_todl, /* value not used; generate log tod */
286 vtype_todlf, /* value not used; generate log file datestamp tod */
287 vtype_todzone, /* value not used; generate time zone only */
288 vtype_todzulu, /* value not used; generate zulu tod */
289 vtype_reply, /* value not used; get reply from headers */
290 vtype_pid, /* value not used; result is pid */
291 vtype_host_lookup, /* value not used; get host name */
5cb8cbc6
PH
292 vtype_load_avg, /* value not used; result is int from os_getloadavg */
293 vtype_pspace, /* partition space; value is T/F for spool/log */
8e669ac1 294 vtype_pinodes /* partition inodes; value is T/F for spool/log */
fb2274d4
TK
295#ifdef EXPERIMENTAL_DOMAINKEYS
296 ,vtype_dk_verify /* Serve request out of DomainKeys verification structure */
84330b7b 297#endif
059ec3d9
PH
298 };
299
300/* This table must be kept in alphabetical order. */
301
302static var_entry var_table[] = {
38a0a95f
PH
303 /* WARNING: Do not invent variables whose names start acl_c or acl_m because
304 they will be confused with user-creatable ACL variables. */
059ec3d9
PH
305 { "acl_verify_message", vtype_stringptr, &acl_verify_message },
306 { "address_data", vtype_stringptr, &deliver_address_data },
307 { "address_file", vtype_stringptr, &address_file },
308 { "address_pipe", vtype_stringptr, &address_pipe },
309 { "authenticated_id", vtype_stringptr, &authenticated_id },
310 { "authenticated_sender",vtype_stringptr, &authenticated_sender },
311 { "authentication_failed",vtype_int, &authentication_failed },
8523533c
TK
312#ifdef EXPERIMENTAL_BRIGHTMAIL
313 { "bmi_alt_location", vtype_stringptr, &bmi_alt_location },
314 { "bmi_base64_tracker_verdict", vtype_stringptr, &bmi_base64_tracker_verdict },
315 { "bmi_base64_verdict", vtype_stringptr, &bmi_base64_verdict },
316 { "bmi_deliver", vtype_int, &bmi_deliver },
317#endif
059ec3d9
PH
318 { "body_linecount", vtype_int, &body_linecount },
319 { "body_zerocount", vtype_int, &body_zerocount },
320 { "bounce_recipient", vtype_stringptr, &bounce_recipient },
321 { "bounce_return_size_limit", vtype_int, &bounce_return_size_limit },
322 { "caller_gid", vtype_gid, &real_gid },
323 { "caller_uid", vtype_uid, &real_uid },
324 { "compile_date", vtype_stringptr, &version_date },
325 { "compile_number", vtype_stringptr, &version_cnumber },
e5a9dba6 326 { "csa_status", vtype_stringptr, &csa_status },
8523533c
TK
327#ifdef WITH_OLD_DEMIME
328 { "demime_errorlevel", vtype_int, &demime_errorlevel },
329 { "demime_reason", vtype_stringptr, &demime_reason },
fb2274d4
TK
330#endif
331#ifdef EXPERIMENTAL_DOMAINKEYS
332 { "dk_domain", vtype_stringptr, &dk_signing_domain },
333 { "dk_is_signed", vtype_dk_verify, NULL },
334 { "dk_result", vtype_dk_verify, NULL },
335 { "dk_selector", vtype_stringptr, &dk_signing_selector },
336 { "dk_sender", vtype_dk_verify, NULL },
337 { "dk_sender_domain", vtype_dk_verify, NULL },
338 { "dk_sender_local_part",vtype_dk_verify, NULL },
339 { "dk_sender_source", vtype_dk_verify, NULL },
340 { "dk_signsall", vtype_dk_verify, NULL },
341 { "dk_status", vtype_dk_verify, NULL },
342 { "dk_testing", vtype_dk_verify, NULL },
8523533c 343#endif
059ec3d9
PH
344 { "dnslist_domain", vtype_stringptr, &dnslist_domain },
345 { "dnslist_text", vtype_stringptr, &dnslist_text },
346 { "dnslist_value", vtype_stringptr, &dnslist_value },
347 { "domain", vtype_stringptr, &deliver_domain },
348 { "domain_data", vtype_stringptr, &deliver_domain_data },
349 { "exim_gid", vtype_gid, &exim_gid },
350 { "exim_path", vtype_stringptr, &exim_path },
351 { "exim_uid", vtype_uid, &exim_uid },
8523533c
TK
352#ifdef WITH_OLD_DEMIME
353 { "found_extension", vtype_stringptr, &found_extension },
8e669ac1 354#endif
059ec3d9
PH
355 { "home", vtype_stringptr, &deliver_home },
356 { "host", vtype_stringptr, &deliver_host },
357 { "host_address", vtype_stringptr, &deliver_host_address },
358 { "host_data", vtype_stringptr, &host_data },
b08b24c8 359 { "host_lookup_deferred",vtype_int, &host_lookup_deferred },
059ec3d9
PH
360 { "host_lookup_failed", vtype_int, &host_lookup_failed },
361 { "inode", vtype_ino, &deliver_inode },
362 { "interface_address", vtype_stringptr, &interface_address },
363 { "interface_port", vtype_int, &interface_port },
364 #ifdef LOOKUP_LDAP
365 { "ldap_dn", vtype_stringptr, &eldap_dn },
366 #endif
367 { "load_average", vtype_load_avg, NULL },
368 { "local_part", vtype_stringptr, &deliver_localpart },
369 { "local_part_data", vtype_stringptr, &deliver_localpart_data },
370 { "local_part_prefix", vtype_stringptr, &deliver_localpart_prefix },
371 { "local_part_suffix", vtype_stringptr, &deliver_localpart_suffix },
372 { "local_scan_data", vtype_stringptr, &local_scan_data },
373 { "local_user_gid", vtype_gid, &local_user_gid },
374 { "local_user_uid", vtype_uid, &local_user_uid },
375 { "localhost_number", vtype_int, &host_number },
5cb8cbc6 376 { "log_inodes", vtype_pinodes, (void *)FALSE },
8e669ac1 377 { "log_space", vtype_pspace, (void *)FALSE },
059ec3d9 378 { "mailstore_basename", vtype_stringptr, &mailstore_basename },
8523533c
TK
379#ifdef WITH_CONTENT_SCAN
380 { "malware_name", vtype_stringptr, &malware_name },
381#endif
059ec3d9
PH
382 { "message_age", vtype_int, &message_age },
383 { "message_body", vtype_msgbody, &message_body },
384 { "message_body_end", vtype_msgbody_end, &message_body_end },
385 { "message_body_size", vtype_int, &message_body_size },
1ab52c69 386 { "message_exim_id", vtype_stringptr, &message_id },
059ec3d9
PH
387 { "message_headers", vtype_msgheaders, NULL },
388 { "message_id", vtype_stringptr, &message_id },
2e0c1448 389 { "message_linecount", vtype_int, &message_linecount },
059ec3d9 390 { "message_size", vtype_int, &message_size },
8523533c
TK
391#ifdef WITH_CONTENT_SCAN
392 { "mime_anomaly_level", vtype_int, &mime_anomaly_level },
393 { "mime_anomaly_text", vtype_stringptr, &mime_anomaly_text },
394 { "mime_boundary", vtype_stringptr, &mime_boundary },
395 { "mime_charset", vtype_stringptr, &mime_charset },
396 { "mime_content_description", vtype_stringptr, &mime_content_description },
397 { "mime_content_disposition", vtype_stringptr, &mime_content_disposition },
398 { "mime_content_id", vtype_stringptr, &mime_content_id },
399 { "mime_content_size", vtype_int, &mime_content_size },
400 { "mime_content_transfer_encoding",vtype_stringptr, &mime_content_transfer_encoding },
401 { "mime_content_type", vtype_stringptr, &mime_content_type },
402 { "mime_decoded_filename", vtype_stringptr, &mime_decoded_filename },
403 { "mime_filename", vtype_stringptr, &mime_filename },
404 { "mime_is_coverletter", vtype_int, &mime_is_coverletter },
405 { "mime_is_multipart", vtype_int, &mime_is_multipart },
406 { "mime_is_rfc822", vtype_int, &mime_is_rfc822 },
407 { "mime_part_count", vtype_int, &mime_part_count },
408#endif
059ec3d9
PH
409 { "n0", vtype_filter_int, &filter_n[0] },
410 { "n1", vtype_filter_int, &filter_n[1] },
411 { "n2", vtype_filter_int, &filter_n[2] },
412 { "n3", vtype_filter_int, &filter_n[3] },
413 { "n4", vtype_filter_int, &filter_n[4] },
414 { "n5", vtype_filter_int, &filter_n[5] },
415 { "n6", vtype_filter_int, &filter_n[6] },
416 { "n7", vtype_filter_int, &filter_n[7] },
417 { "n8", vtype_filter_int, &filter_n[8] },
418 { "n9", vtype_filter_int, &filter_n[9] },
419 { "original_domain", vtype_stringptr, &deliver_domain_orig },
420 { "original_local_part", vtype_stringptr, &deliver_localpart_orig },
421 { "originator_gid", vtype_gid, &originator_gid },
422 { "originator_uid", vtype_uid, &originator_uid },
423 { "parent_domain", vtype_stringptr, &deliver_domain_parent },
424 { "parent_local_part", vtype_stringptr, &deliver_localpart_parent },
425 { "pid", vtype_pid, NULL },
426 { "primary_hostname", vtype_stringptr, &primary_hostname },
fffda43a
TK
427 { "prvscheck_address", vtype_stringptr, &prvscheck_address },
428 { "prvscheck_keynum", vtype_stringptr, &prvscheck_keynum },
429 { "prvscheck_result", vtype_stringptr, &prvscheck_result },
059ec3d9
PH
430 { "qualify_domain", vtype_stringptr, &qualify_domain_sender },
431 { "qualify_recipient", vtype_stringptr, &qualify_domain_recipient },
432 { "rcpt_count", vtype_int, &rcpt_count },
433 { "rcpt_defer_count", vtype_int, &rcpt_defer_count },
434 { "rcpt_fail_count", vtype_int, &rcpt_fail_count },
435 { "received_count", vtype_int, &received_count },
436 { "received_for", vtype_stringptr, &received_for },
437 { "received_protocol", vtype_stringptr, &received_protocol },
7dbf77c9 438 { "received_time", vtype_int, &received_time },
059ec3d9 439 { "recipient_data", vtype_stringptr, &recipient_data },
8e669ac1 440 { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
059ec3d9
PH
441 { "recipients", vtype_recipients, NULL },
442 { "recipients_count", vtype_int, &recipients_count },
8523533c
TK
443#ifdef WITH_CONTENT_SCAN
444 { "regex_match_string", vtype_stringptr, &regex_match_string },
445#endif
059ec3d9
PH
446 { "reply_address", vtype_reply, NULL },
447 { "return_path", vtype_stringptr, &return_path },
448 { "return_size_limit", vtype_int, &bounce_return_size_limit },
449 { "runrc", vtype_int, &runrc },
450 { "self_hostname", vtype_stringptr, &self_hostname },
451 { "sender_address", vtype_stringptr, &sender_address },
2a3eea10 452 { "sender_address_data", vtype_stringptr, &sender_address_data },
059ec3d9
PH
453 { "sender_address_domain", vtype_domain, &sender_address },
454 { "sender_address_local_part", vtype_localpart, &sender_address },
455 { "sender_data", vtype_stringptr, &sender_data },
456 { "sender_fullhost", vtype_stringptr, &sender_fullhost },
457 { "sender_helo_name", vtype_stringptr, &sender_helo_name },
458 { "sender_host_address", vtype_stringptr, &sender_host_address },
459 { "sender_host_authenticated",vtype_stringptr, &sender_host_authenticated },
460 { "sender_host_name", vtype_host_lookup, NULL },
461 { "sender_host_port", vtype_int, &sender_host_port },
462 { "sender_ident", vtype_stringptr, &sender_ident },
870f6ba8
TF
463 { "sender_rate", vtype_stringptr, &sender_rate },
464 { "sender_rate_limit", vtype_stringptr, &sender_rate_limit },
465 { "sender_rate_period", vtype_stringptr, &sender_rate_period },
059ec3d9 466 { "sender_rcvhost", vtype_stringptr, &sender_rcvhost },
8e669ac1
PH
467 { "sender_verify_failure",vtype_stringptr, &sender_verify_failure },
468 { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname },
3ee512ff
PH
469 { "smtp_command", vtype_stringptr, &smtp_cmd_buffer },
470 { "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument },
059ec3d9
PH
471 { "sn0", vtype_filter_int, &filter_sn[0] },
472 { "sn1", vtype_filter_int, &filter_sn[1] },
473 { "sn2", vtype_filter_int, &filter_sn[2] },
474 { "sn3", vtype_filter_int, &filter_sn[3] },
475 { "sn4", vtype_filter_int, &filter_sn[4] },
476 { "sn5", vtype_filter_int, &filter_sn[5] },
477 { "sn6", vtype_filter_int, &filter_sn[6] },
478 { "sn7", vtype_filter_int, &filter_sn[7] },
479 { "sn8", vtype_filter_int, &filter_sn[8] },
480 { "sn9", vtype_filter_int, &filter_sn[9] },
8523533c
TK
481#ifdef WITH_CONTENT_SCAN
482 { "spam_bar", vtype_stringptr, &spam_bar },
483 { "spam_report", vtype_stringptr, &spam_report },
484 { "spam_score", vtype_stringptr, &spam_score },
485 { "spam_score_int", vtype_stringptr, &spam_score_int },
486#endif
487#ifdef EXPERIMENTAL_SPF
488 { "spf_header_comment", vtype_stringptr, &spf_header_comment },
489 { "spf_received", vtype_stringptr, &spf_received },
490 { "spf_result", vtype_stringptr, &spf_result },
491 { "spf_smtp_comment", vtype_stringptr, &spf_smtp_comment },
492#endif
059ec3d9 493 { "spool_directory", vtype_stringptr, &spool_directory },
5cb8cbc6 494 { "spool_inodes", vtype_pinodes, (void *)TRUE },
8e669ac1 495 { "spool_space", vtype_pspace, (void *)TRUE },
8523533c
TK
496#ifdef EXPERIMENTAL_SRS
497 { "srs_db_address", vtype_stringptr, &srs_db_address },
498 { "srs_db_key", vtype_stringptr, &srs_db_key },
499 { "srs_orig_recipient", vtype_stringptr, &srs_orig_recipient },
500 { "srs_orig_sender", vtype_stringptr, &srs_orig_sender },
501 { "srs_recipient", vtype_stringptr, &srs_recipient },
502 { "srs_status", vtype_stringptr, &srs_status },
503#endif
059ec3d9
PH
504 { "thisaddress", vtype_stringptr, &filter_thisaddress },
505 { "tls_certificate_verified", vtype_int, &tls_certificate_verified },
506 { "tls_cipher", vtype_stringptr, &tls_cipher },
507 { "tls_peerdn", vtype_stringptr, &tls_peerdn },
508 { "tod_bsdinbox", vtype_todbsdin, NULL },
509 { "tod_epoch", vtype_tode, NULL },
510 { "tod_full", vtype_todf, NULL },
511 { "tod_log", vtype_todl, NULL },
512 { "tod_logfile", vtype_todlf, NULL },
513 { "tod_zone", vtype_todzone, NULL },
514 { "tod_zulu", vtype_todzulu, NULL },
515 { "value", vtype_stringptr, &lookup_value },
516 { "version_number", vtype_stringptr, &version_string },
517 { "warn_message_delay", vtype_stringptr, &warnmsg_delay },
518 { "warn_message_recipient",vtype_stringptr, &warnmsg_recipients },
519 { "warn_message_recipients",vtype_stringptr,&warnmsg_recipients },
520 { "warnmsg_delay", vtype_stringptr, &warnmsg_delay },
521 { "warnmsg_recipient", vtype_stringptr, &warnmsg_recipients },
522 { "warnmsg_recipients", vtype_stringptr, &warnmsg_recipients }
523};
524
525static int var_table_size = sizeof(var_table)/sizeof(var_entry);
526static uschar var_buffer[256];
527static BOOL malformed_header;
528
529/* For textual hashes */
530
531static char *hashcodes = "abcdefghijklmnopqrtsuvwxyz"
532 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
533 "0123456789";
534
535enum { HMAC_MD5, HMAC_SHA1 };
536
537/* For numeric hashes */
538
539static unsigned int prime[] = {
540 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
541 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
542 73, 79, 83, 89, 97, 101, 103, 107, 109, 113};
543
544/* For printing modes in symbolic form */
545
546static uschar *mtable_normal[] =
547 { US"---", US"--x", US"-w-", US"-wx", US"r--", US"r-x", US"rw-", US"rwx" };
548
549static uschar *mtable_setid[] =
550 { US"--S", US"--s", US"-wS", US"-ws", US"r-S", US"r-s", US"rwS", US"rws" };
551
552static uschar *mtable_sticky[] =
553 { US"--T", US"--t", US"-wT", US"-wt", US"r-T", US"r-t", US"rwT", US"rwt" };
554
555
556
557/*************************************************
558* Tables for UTF-8 support *
559*************************************************/
560
561/* Table of the number of extra characters, indexed by the first character
562masked with 0x3f. The highest number for a valid UTF-8 character is in fact
5630x3d. */
564
565static uschar utf8_table1[] = {
566 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
567 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
568 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
569 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
570
571/* These are the masks for the data bits in the first byte of a character,
572indexed by the number of additional bytes. */
573
574static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
575
576/* Get the next UTF-8 character, advancing the pointer. */
577
578#define GETUTF8INC(c, ptr) \
579 c = *ptr++; \
580 if ((c & 0xc0) == 0xc0) \
581 { \
582 int a = utf8_table1[c & 0x3f]; /* Number of additional bytes */ \
583 int s = 6*a; \
584 c = (c & utf8_table2[a]) << s; \
585 while (a-- > 0) \
586 { \
587 s -= 6; \
588 c |= (*ptr++ & 0x3f) << s; \
589 } \
590 }
591
592
593/*************************************************
594* Binary chop search on a table *
595*************************************************/
596
597/* This is used for matching expansion items and operators.
598
599Arguments:
600 name the name that is being sought
601 table the table to search
602 table_size the number of items in the table
603
604Returns: the offset in the table, or -1
605*/
606
607static int
608chop_match(uschar *name, uschar **table, int table_size)
609{
610uschar **bot = table;
611uschar **top = table + table_size;
612
613while (top > bot)
614 {
615 uschar **mid = bot + (top - bot)/2;
616 int c = Ustrcmp(name, *mid);
617 if (c == 0) return mid - table;
618 if (c > 0) bot = mid + 1; else top = mid;
619 }
620
621return -1;
622}
623
624
625
626/*************************************************
627* Check a condition string *
628*************************************************/
629
630/* This function is called to expand a string, and test the result for a "true"
631or "false" value. Failure of the expansion yields FALSE; logged unless it was a
632forced fail or lookup defer. All store used by the function can be released on
633exit.
634
635Arguments:
636 condition the condition string
637 m1 text to be incorporated in panic error
638 m2 ditto
639
640Returns: TRUE if condition is met, FALSE if not
641*/
642
643BOOL
644expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
645{
646int rc;
647void *reset_point = store_get(0);
648uschar *ss = expand_string(condition);
649if (ss == NULL)
650 {
651 if (!expand_string_forcedfail && !search_find_defer)
652 log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand condition \"%s\" "
653 "for %s %s: %s", condition, m1, m2, expand_string_message);
654 return FALSE;
655 }
656rc = ss[0] != 0 && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
657 strcmpic(ss, US"false") != 0;
658store_reset(reset_point);
659return rc;
660}
661
662
663
664/*************************************************
665* Pick out a name from a string *
666*************************************************/
667
668/* If the name is too long, it is silently truncated.
669
670Arguments:
671 name points to a buffer into which to put the name
672 max is the length of the buffer
673 s points to the first alphabetic character of the name
674 extras chars other than alphanumerics to permit
675
676Returns: pointer to the first character after the name
677
678Note: The test for *s != 0 in the while loop is necessary because
679Ustrchr() yields non-NULL if the character is zero (which is not something
680I expected). */
681
682static uschar *
683read_name(uschar *name, int max, uschar *s, uschar *extras)
684{
685int ptr = 0;
686while (*s != 0 && (isalnum(*s) || Ustrchr(extras, *s) != NULL))
687 {
688 if (ptr < max-1) name[ptr++] = *s;
689 s++;
690 }
691name[ptr] = 0;
692return s;
693}
694
695
696
697/*************************************************
698* Pick out the rest of a header name *
699*************************************************/
700
701/* A variable name starting $header_ (or just $h_ for those who like
702abbreviations) might not be the complete header name because headers can
703contain any printing characters in their names, except ':'. This function is
704called to read the rest of the name, chop h[eader]_ off the front, and put ':'
705on the end, if the name was terminated by white space.
706
707Arguments:
708 name points to a buffer in which the name read so far exists
709 max is the length of the buffer
710 s points to the first character after the name so far, i.e. the
711 first non-alphameric character after $header_xxxxx
712
713Returns: a pointer to the first character after the header name
714*/
715
716static uschar *
717read_header_name(uschar *name, int max, uschar *s)
718{
719int prelen = Ustrchr(name, '_') - name + 1;
720int ptr = Ustrlen(name) - prelen;
721if (ptr > 0) memmove(name, name+prelen, ptr);
722while (mac_isgraph(*s) && *s != ':')
723 {
724 if (ptr < max-1) name[ptr++] = *s;
725 s++;
726 }
727if (*s == ':') s++;
728name[ptr++] = ':';
729name[ptr] = 0;
730return s;
731}
732
733
734
735/*************************************************
736* Pick out a number from a string *
737*************************************************/
738
739/* Arguments:
740 n points to an integer into which to put the number
741 s points to the first digit of the number
742
743Returns: a pointer to the character after the last digit
744*/
745
746static uschar *
747read_number(int *n, uschar *s)
748{
749*n = 0;
750while (isdigit(*s)) *n = *n * 10 + (*s++ - '0');
751return s;
752}
753
754
755
756/*************************************************
757* Extract keyed subfield from a string *
758*************************************************/
759
760/* The yield is in dynamic store; NULL means that the key was not found.
761
762Arguments:
763 key points to the name of the key
764 s points to the string from which to extract the subfield
765
766Returns: NULL if the subfield was not found, or
767 a pointer to the subfield's data
768*/
769
770static uschar *
771expand_getkeyed(uschar *key, uschar *s)
772{
773int length = Ustrlen(key);
774while (isspace(*s)) s++;
775
776/* Loop to search for the key */
777
778while (*s != 0)
779 {
780 int dkeylength;
781 uschar *data;
782 uschar *dkey = s;
783
784 while (*s != 0 && *s != '=' && !isspace(*s)) s++;
785 dkeylength = s - dkey;
786 while (isspace(*s)) s++;
787 if (*s == '=') while (isspace((*(++s))));
788
789 data = string_dequote(&s);
790 if (length == dkeylength && strncmpic(key, dkey, length) == 0)
791 return data;
792
793 while (isspace(*s)) s++;
794 }
795
796return NULL;
797}
798
799
800
801
802/*************************************************
803* Extract numbered subfield from string *
804*************************************************/
805
806/* Extracts a numbered field from a string that is divided by tokens - for
807example a line from /etc/passwd is divided by colon characters. First field is
808numbered one. Negative arguments count from the right. Zero returns the whole
809string. Returns NULL if there are insufficient tokens in the string
810
811***WARNING***
812Modifies final argument - this is a dynamically generated string, so that's OK.
813
814Arguments:
815 field number of field to be extracted,
816 first field = 1, whole string = 0, last field = -1
817 separators characters that are used to break string into tokens
818 s points to the string from which to extract the subfield
819
820Returns: NULL if the field was not found,
821 a pointer to the field's data inside s (modified to add 0)
822*/
823
824static uschar *
825expand_gettokened (int field, uschar *separators, uschar *s)
826{
827int sep = 1;
828int count;
829uschar *ss = s;
830uschar *fieldtext = NULL;
831
832if (field == 0) return s;
833
834/* Break the line up into fields in place; for field > 0 we stop when we have
835done the number of fields we want. For field < 0 we continue till the end of
836the string, counting the number of fields. */
837
838count = (field > 0)? field : INT_MAX;
839
840while (count-- > 0)
841 {
842 size_t len;
843
844 /* Previous field was the last one in the string. For a positive field
845 number, this means there are not enough fields. For a negative field number,
846 check that there are enough, and scan back to find the one that is wanted. */
847
848 if (sep == 0)
849 {
850 if (field > 0 || (-field) > (INT_MAX - count - 1)) return NULL;
851 if ((-field) == (INT_MAX - count - 1)) return s;
852 while (field++ < 0)
853 {
854 ss--;
855 while (ss[-1] != 0) ss--;
856 }
857 fieldtext = ss;
858 break;
859 }
860
861 /* Previous field was not last in the string; save its start and put a
862 zero at its end. */
863
864 fieldtext = ss;
865 len = Ustrcspn(ss, separators);
866 sep = ss[len];
867 ss[len] = 0;
868 ss += len + 1;
869 }
870
871return fieldtext;
872}
873
874
875
876/*************************************************
877* Extract a substring from a string *
878*************************************************/
879
880/* Perform the ${substr or ${length expansion operations.
881
882Arguments:
883 subject the input string
884 value1 the offset from the start of the input string to the start of
885 the output string; if negative, count from the right.
886 value2 the length of the output string, or negative (-1) for unset
887 if value1 is positive, unset means "all after"
888 if value1 is negative, unset means "all before"
889 len set to the length of the returned string
890
891Returns: pointer to the output string, or NULL if there is an error
892*/
893
894static uschar *
895extract_substr(uschar *subject, int value1, int value2, int *len)
896{
897int sublen = Ustrlen(subject);
898
899if (value1 < 0) /* count from right */
900 {
901 value1 += sublen;
902
903 /* If the position is before the start, skip to the start, and adjust the
904 length. If the length ends up negative, the substring is null because nothing
905 can precede. This falls out naturally when the length is unset, meaning "all
906 to the left". */
907
908 if (value1 < 0)
909 {
910 value2 += value1;
911 if (value2 < 0) value2 = 0;
912 value1 = 0;
913 }
914
915 /* Otherwise an unset length => characters before value1 */
916
917 else if (value2 < 0)
918 {
919 value2 = value1;
920 value1 = 0;
921 }
922 }
923
924/* For a non-negative offset, if the starting position is past the end of the
925string, the result will be the null string. Otherwise, an unset length means
926"rest"; just set it to the maximum - it will be cut down below if necessary. */
927
928else
929 {
930 if (value1 > sublen)
931 {
932 value1 = sublen;
933 value2 = 0;
934 }
935 else if (value2 < 0) value2 = sublen;
936 }
937
938/* Cut the length down to the maximum possible for the offset value, and get
939the required characters. */
940
941if (value1 + value2 > sublen) value2 = sublen - value1;
942*len = value2;
943return subject + value1;
944}
945
946
947
948
949/*************************************************
950* Old-style hash of a string *
951*************************************************/
952
953/* Perform the ${hash expansion operation.
954
955Arguments:
956 subject the input string (an expanded substring)
957 value1 the length of the output string; if greater or equal to the
958 length of the input string, the input string is returned
959 value2 the number of hash characters to use, or 26 if negative
960 len set to the length of the returned string
961
962Returns: pointer to the output string, or NULL if there is an error
963*/
964
965static uschar *
966compute_hash(uschar *subject, int value1, int value2, int *len)
967{
968int sublen = Ustrlen(subject);
969
970if (value2 < 0) value2 = 26;
971else if (value2 > Ustrlen(hashcodes))
972 {
973 expand_string_message =
974 string_sprintf("hash count \"%d\" too big", value2);
975 return NULL;
976 }
977
978/* Calculate the hash text. We know it is shorter than the original string, so
979can safely place it in subject[] (we know that subject is always itself an
980expanded substring). */
981
982if (value1 < sublen)
983 {
984 int c;
985 int i = 0;
986 int j = value1;
987 while ((c = (subject[j])) != 0)
988 {
989 int shift = (c + j++) & 7;
990 subject[i] ^= (c << shift) | (c >> (8-shift));
991 if (++i >= value1) i = 0;
992 }
993 for (i = 0; i < value1; i++)
994 subject[i] = hashcodes[(subject[i]) % value2];
995 }
996else value1 = sublen;
997
998*len = value1;
999return subject;
1000}
1001
1002
1003
1004
1005/*************************************************
1006* Numeric hash of a string *
1007*************************************************/
1008
1009/* Perform the ${nhash expansion operation. The first characters of the
1010string are treated as most important, and get the highest prime numbers.
1011
1012Arguments:
1013 subject the input string
1014 value1 the maximum value of the first part of the result
1015 value2 the maximum value of the second part of the result,
1016 or negative to produce only a one-part result
1017 len set to the length of the returned string
1018
1019Returns: pointer to the output string, or NULL if there is an error.
1020*/
1021
1022static uschar *
1023compute_nhash (uschar *subject, int value1, int value2, int *len)
1024{
1025uschar *s = subject;
1026int i = 0;
1027unsigned long int total = 0; /* no overflow */
1028
1029while (*s != 0)
1030 {
1031 if (i == 0) i = sizeof(prime)/sizeof(int) - 1;
1032 total += prime[i--] * (unsigned int)(*s++);
1033 }
1034
1035/* If value2 is unset, just compute one number */
1036
1037if (value2 < 0)
1038 {
1039 s = string_sprintf("%d", total % value1);
1040 }
1041
1042/* Otherwise do a div/mod hash */
1043
1044else
1045 {
1046 total = total % (value1 * value2);
1047 s = string_sprintf("%d/%d", total/value2, total % value2);
1048 }
1049
1050*len = Ustrlen(s);
1051return s;
1052}
1053
1054
1055
1056
1057
1058/*************************************************
1059* Find the value of a header or headers *
1060*************************************************/
1061
1062/* Multiple instances of the same header get concatenated, and this function
1063can also return a concatenation of all the header lines. When concatenating
1064specific headers that contain lists of addresses, a comma is inserted between
1065them. Otherwise we use a straight concatenation. Because some messages can have
1066pathologically large number of lines, there is a limit on the length that is
1067returned. Also, to avoid massive store use which would result from using
1068string_cat() as it copies and extends strings, we do a preliminary pass to find
1069out exactly how much store will be needed. On "normal" messages this will be
1070pretty trivial.
1071
1072Arguments:
1073 name the name of the header, without the leading $header_ or $h_,
1074 or NULL if a concatenation of all headers is required
1075 exists_only TRUE if called from a def: test; don't need to build a string;
1076 just return a string that is not "" and not "0" if the header
1077 exists
1078 newsize return the size of memory block that was obtained; may be NULL
1079 if exists_only is TRUE
1080 want_raw TRUE if called for $rh_ or $rheader_ variables; no processing,
1081 other than concatenating, will be done on the header
1082 charset name of charset to translate MIME words to; used only if
1083 want_raw is false; if NULL, no translation is done (this is
1084 used for $bh_ and $bheader_)
1085
1086Returns: NULL if the header does not exist, else a pointer to a new
1087 store block
1088*/
1089
1090static uschar *
1091find_header(uschar *name, BOOL exists_only, int *newsize, BOOL want_raw,
1092 uschar *charset)
1093{
1094BOOL found = name == NULL;
1095int comma = 0;
1096int len = found? 0 : Ustrlen(name);
1097int i;
1098uschar *yield = NULL;
1099uschar *ptr = NULL;
1100
1101/* Loop for two passes - saves code repetition */
1102
1103for (i = 0; i < 2; i++)
1104 {
1105 int size = 0;
1106 header_line *h;
1107
1108 for (h = header_list; size < header_insert_maxlen && h != NULL; h = h->next)
1109 {
1110 if (h->type != htype_old && h->text != NULL) /* NULL => Received: placeholder */
1111 {
1112 if (name == NULL || (len <= h->slen && strncmpic(name, h->text, len) == 0))
1113 {
1114 int ilen;
1115 uschar *t;
1116
1117 if (exists_only) return US"1"; /* don't need actual string */
1118 found = TRUE;
1119 t = h->text + len; /* text to insert */
1120 if (!want_raw) /* unless wanted raw, */
1121 while (isspace(*t)) t++; /* remove leading white space */
1122 ilen = h->slen - (t - h->text); /* length to insert */
1123
1124 /* Set comma = 1 if handling a single header and it's one of those
1125 that contains an address list, except when asked for raw headers. Only
1126 need to do this once. */
1127
1128 if (!want_raw && name != NULL && comma == 0 &&
1129 Ustrchr("BCFRST", h->type) != NULL)
1130 comma = 1;
1131
1132 /* First pass - compute total store needed; second pass - compute
1133 total store used, including this header. */
1134
1135 size += ilen + comma;
1136
1137 /* Second pass - concatentate the data, up to a maximum. Note that
1138 the loop stops when size hits the limit. */
1139
1140 if (i != 0)
1141 {
1142 if (size > header_insert_maxlen)
1143 {
1144 ilen -= size - header_insert_maxlen;
1145 comma = 0;
1146 }
1147 Ustrncpy(ptr, t, ilen);
1148 ptr += ilen;
1149 if (comma != 0 && ilen > 0)
1150 {
1151 ptr[-1] = ',';
1152 *ptr++ = '\n';
1153 }
1154 }
1155 }
1156 }
1157 }
1158
1159 /* At end of first pass, truncate size if necessary, and get the buffer
1160 to hold the data, returning the buffer size. */
1161
1162 if (i == 0)
1163 {
1164 if (!found) return NULL;
1165 if (size > header_insert_maxlen) size = header_insert_maxlen;
1166 *newsize = size + 1;
1167 ptr = yield = store_get(*newsize);
1168 }
1169 }
1170
1171/* Remove a redundant added comma if present */
1172
1173if (comma != 0 && ptr > yield) ptr -= 2;
1174
1175/* That's all we do for raw header expansion. */
1176
1177if (want_raw)
1178 {
1179 *ptr = 0;
1180 }
1181
1182/* Otherwise, we remove trailing whitespace, including newlines. Then we do RFC
11832047 decoding, translating the charset if requested. The rfc2047_decode2()
1184function can return an error with decoded data if the charset translation
1185fails. If decoding fails, it returns NULL. */
1186
1187else
1188 {
1189 uschar *decoded, *error;
1190 while (ptr > yield && isspace(ptr[-1])) ptr--;
1191 *ptr = 0;
a0d6ba8a
PH
1192 decoded = rfc2047_decode2(yield, check_rfc2047_length, charset, '?', NULL,
1193 newsize, &error);
059ec3d9
PH
1194 if (error != NULL)
1195 {
1196 DEBUG(D_any) debug_printf("*** error in RFC 2047 decoding: %s\n"
1197 " input was: %s\n", error, yield);
1198 }
1199 if (decoded != NULL) yield = decoded;
1200 }
1201
1202return yield;
1203}
1204
1205
1206
1207
1208/*************************************************
1209* Find value of a variable *
1210*************************************************/
1211
1212/* The table of variables is kept in alphabetic order, so we can search it
1213using a binary chop. The "choplen" variable is nothing to do with the binary
1214chop.
1215
1216Arguments:
1217 name the name of the variable being sought
1218 exists_only TRUE if this is a def: test; passed on to find_header()
1219 skipping TRUE => skip any processing evaluation; this is not the same as
1220 exists_only because def: may test for values that are first
1221 evaluated here
1222 newsize pointer to an int which is initially zero; if the answer is in
1223 a new memory buffer, *newsize is set to its size
1224
1225Returns: NULL if the variable does not exist, or
1226 a pointer to the variable's contents, or
1227 something non-NULL if exists_only is TRUE
1228*/
1229
1230static uschar *
1231find_variable(uschar *name, BOOL exists_only, BOOL skipping, int *newsize)
1232{
1233int first = 0;
1234int last = var_table_size;
1235
38a0a95f
PH
1236/* Handle ACL variables, whose names are of the form acl_cxxx or acl_mxxx.
1237Originally, xxx had to be a number in the range 0-9 (later 0-19), but from
1238release 4.64 onwards arbitrary names are permitted, as long as the first 5
1239characters are acl_c or acl_m (this gave backwards compatibility at the
1240changeover). There may be built-in variables whose names start acl_ but they
1241should never start acl_c or acl_m. This slightly messy specification is a
1242consequence of the history, needless to say.
47ca6d6c 1243
38a0a95f
PH
1244If an ACL variable does not exist, treat it as empty, unless strict_acl_vars is
1245set, in which case give an error. */
47ca6d6c 1246
38a0a95f
PH
1247if (Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0)
1248 {
1249 tree_node *node =
1250 tree_search((name[4] == 'c')? acl_var_c : acl_var_m, name + 4);
1251 return (node == NULL)? (strict_acl_vars? NULL : US"") : node->data.ptr;
47ca6d6c
PH
1252 }
1253
38a0a95f 1254/* Handle $auth<n> variables. */
f78eb7c6
PH
1255
1256if (Ustrncmp(name, "auth", 4) == 0)
1257 {
1258 uschar *endptr;
1259 int n = Ustrtoul(name + 4, &endptr, 10);
1260 if (*endptr == 0 && n != 0 && n <= AUTH_VARS)
1261 return (auth_vars[n-1] == NULL)? US"" : auth_vars[n-1];
1262 }
1263
47ca6d6c
PH
1264/* For all other variables, search the table */
1265
059ec3d9
PH
1266while (last > first)
1267 {
1268 uschar *s, *domain;
1269 uschar **ss;
1270 int middle = (first + last)/2;
1271 int c = Ustrcmp(name, var_table[middle].name);
1272
1273 if (c > 0) { first = middle + 1; continue; }
1274 if (c < 0) { last = middle; continue; }
1275
1276 /* Found an existing variable. If in skipping state, the value isn't needed,
47ca6d6c 1277 and we want to avoid processing (such as looking up the host name). */
059ec3d9
PH
1278
1279 if (skipping) return US"";
1280
1281 switch (var_table[middle].type)
1282 {
fb2274d4
TK
1283#ifdef EXPERIMENTAL_DOMAINKEYS
1284
1285 case vtype_dk_verify:
cacfbf29 1286 if (dk_verify_block == NULL) return US"";
fb2274d4
TK
1287 s = NULL;
1288 if (Ustrcmp(var_table[middle].name, "dk_result") == 0)
1289 s = dk_verify_block->result_string;
1290 if (Ustrcmp(var_table[middle].name, "dk_sender") == 0)
1291 s = dk_verify_block->address;
1292 if (Ustrcmp(var_table[middle].name, "dk_sender_domain") == 0)
1293 s = dk_verify_block->domain;
1294 if (Ustrcmp(var_table[middle].name, "dk_sender_local_part") == 0)
1295 s = dk_verify_block->local_part;
84330b7b 1296
fb2274d4
TK
1297 if (Ustrcmp(var_table[middle].name, "dk_sender_source") == 0)
1298 switch(dk_verify_block->address_source) {
a8d97c8a
PH
1299 case DK_EXIM_ADDRESS_NONE: s = US"0"; break;
1300 case DK_EXIM_ADDRESS_FROM_FROM: s = US"from"; break;
1301 case DK_EXIM_ADDRESS_FROM_SENDER: s = US"sender"; break;
fb2274d4
TK
1302 }
1303
1304 if (Ustrcmp(var_table[middle].name, "dk_status") == 0)
1305 switch(dk_verify_block->result) {
a8d97c8a
PH
1306 case DK_EXIM_RESULT_ERR: s = US"error"; break;
1307 case DK_EXIM_RESULT_BAD_FORMAT: s = US"bad format"; break;
1308 case DK_EXIM_RESULT_NO_KEY: s = US"no key"; break;
1309 case DK_EXIM_RESULT_NO_SIGNATURE: s = US"no signature"; break;
1310 case DK_EXIM_RESULT_REVOKED: s = US"revoked"; break;
1311 case DK_EXIM_RESULT_NON_PARTICIPANT: s = US"non-participant"; break;
1312 case DK_EXIM_RESULT_GOOD: s = US"good"; break;
1313 case DK_EXIM_RESULT_BAD: s = US"bad"; break;
fb2274d4 1314 }
84330b7b 1315
fb2274d4 1316 if (Ustrcmp(var_table[middle].name, "dk_signsall") == 0)
a8d97c8a 1317 s = (dk_verify_block->signsall)? US"1" : US"0";
84330b7b 1318
fb2274d4 1319 if (Ustrcmp(var_table[middle].name, "dk_testing") == 0)
a8d97c8a 1320 s = (dk_verify_block->testing)? US"1" : US"0";
84330b7b 1321
fb2274d4 1322 if (Ustrcmp(var_table[middle].name, "dk_is_signed") == 0)
a8d97c8a 1323 s = (dk_verify_block->is_signed)? US"1" : US"0";
84330b7b 1324
fb2274d4
TK
1325 return (s == NULL)? US"" : s;
1326#endif
1327
9a26b6b2
PH
1328 case vtype_filter_int:
1329 if (!filter_running) return NULL;
1330 /* Fall through */
1331 /* VVVVVVVVVVVV */
059ec3d9
PH
1332 case vtype_int:
1333 sprintf(CS var_buffer, "%d", *(int *)(var_table[middle].value)); /* Integer */
1334 return var_buffer;
1335
1336 case vtype_ino:
1337 sprintf(CS var_buffer, "%ld", (long int)(*(ino_t *)(var_table[middle].value))); /* Inode */
1338 return var_buffer;
1339
1340 case vtype_gid:
1341 sprintf(CS var_buffer, "%ld", (long int)(*(gid_t *)(var_table[middle].value))); /* gid */
1342 return var_buffer;
1343
1344 case vtype_uid:
1345 sprintf(CS var_buffer, "%ld", (long int)(*(uid_t *)(var_table[middle].value))); /* uid */
1346 return var_buffer;
1347
1348 case vtype_stringptr: /* Pointer to string */
1349 s = *((uschar **)(var_table[middle].value));
1350 return (s == NULL)? US"" : s;
1351
1352 case vtype_pid:
1353 sprintf(CS var_buffer, "%d", (int)getpid()); /* pid */
1354 return var_buffer;
1355
1356 case vtype_load_avg:
1357 sprintf(CS var_buffer, "%d", os_getloadavg()); /* load_average */
1358 return var_buffer;
1359
1360 case vtype_host_lookup: /* Lookup if not done so */
1361 if (sender_host_name == NULL && sender_host_address != NULL &&
1362 !host_lookup_failed && host_name_lookup() == OK)
1363 host_build_sender_fullhost();
1364 return (sender_host_name == NULL)? US"" : sender_host_name;
1365
1366 case vtype_localpart: /* Get local part from address */
1367 s = *((uschar **)(var_table[middle].value));
1368 if (s == NULL) return US"";
1369 domain = Ustrrchr(s, '@');
1370 if (domain == NULL) return s;
1371 if (domain - s > sizeof(var_buffer) - 1)
1372 log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than %d in "
1373 "string expansion", sizeof(var_buffer));
1374 Ustrncpy(var_buffer, s, domain - s);
1375 var_buffer[domain - s] = 0;
1376 return var_buffer;
1377
1378 case vtype_domain: /* Get domain from address */
1379 s = *((uschar **)(var_table[middle].value));
1380 if (s == NULL) return US"";
1381 domain = Ustrrchr(s, '@');
1382 return (domain == NULL)? US"" : domain + 1;
1383
1384 case vtype_msgheaders:
1385 return find_header(NULL, exists_only, newsize, FALSE, NULL);
1386
1387 case vtype_msgbody: /* Pointer to msgbody string */
1388 case vtype_msgbody_end: /* Ditto, the end of the msg */
1389 ss = (uschar **)(var_table[middle].value);
1390 if (*ss == NULL && deliver_datafile >= 0) /* Read body when needed */
1391 {
1392 uschar *body;
0d7eb84a 1393 off_t start_offset = SPOOL_DATA_START_OFFSET;
059ec3d9
PH
1394 int len = message_body_visible;
1395 if (len > message_size) len = message_size;
1396 *ss = body = store_malloc(len+1);
1397 body[0] = 0;
1398 if (var_table[middle].type == vtype_msgbody_end)
1399 {
1400 struct stat statbuf;
1401 if (fstat(deliver_datafile, &statbuf) == 0)
1402 {
1403 start_offset = statbuf.st_size - len;
1404 if (start_offset < SPOOL_DATA_START_OFFSET)
1405 start_offset = SPOOL_DATA_START_OFFSET;
1406 }
1407 }
1408 lseek(deliver_datafile, start_offset, SEEK_SET);
1409 len = read(deliver_datafile, body, len);
1410 if (len > 0)
1411 {
1412 body[len] = 0;
1413 while (len > 0)
1414 {
1415 if (body[--len] == '\n' || body[len] == 0) body[len] = ' ';
1416 }
1417 }
1418 }
1419 return (*ss == NULL)? US"" : *ss;
1420
1421 case vtype_todbsdin: /* BSD inbox time of day */
1422 return tod_stamp(tod_bsdin);
1423
1424 case vtype_tode: /* Unix epoch time of day */
1425 return tod_stamp(tod_epoch);
1426
1427 case vtype_todf: /* Full time of day */
1428 return tod_stamp(tod_full);
1429
1430 case vtype_todl: /* Log format time of day */
1431 return tod_stamp(tod_log_bare); /* (without timezone) */
1432
1433 case vtype_todzone: /* Time zone offset only */
1434 return tod_stamp(tod_zone);
1435
1436 case vtype_todzulu: /* Zulu time */
1437 return tod_stamp(tod_zulu);
1438
1439 case vtype_todlf: /* Log file datestamp tod */
1440 return tod_stamp(tod_log_datestamp);
1441
1442 case vtype_reply: /* Get reply address */
c8ea1597 1443 s = find_header(US"reply-to:", exists_only, newsize, TRUE,
059ec3d9 1444 headers_charset);
6979240a 1445 if (s != NULL) while (isspace(*s)) s++;
059ec3d9 1446 if (s == NULL || *s == 0)
41a13e0a
PH
1447 {
1448 *newsize = 0; /* For the *s==0 case */
c8ea1597
PH
1449 s = find_header(US"from:", exists_only, newsize, TRUE, headers_charset);
1450 }
1451 if (s != NULL)
1452 {
1453 uschar *t;
1454 while (isspace(*s)) s++;
1455 for (t = s; *t != 0; t++) if (*t == '\n') *t = ' ';
6979240a
PH
1456 while (t > s && isspace(t[-1])) t--;
1457 *t = 0;
41a13e0a 1458 }
059ec3d9
PH
1459 return (s == NULL)? US"" : s;
1460
1461 /* A recipients list is available only during system message filtering,
1462 during ACL processing after DATA, and while expanding pipe commands
1463 generated from a system filter, but not elsewhere. */
1464
1465 case vtype_recipients:
1466 if (!enable_dollar_recipients) return NULL; else
1467 {
1468 int size = 128;
1469 int ptr = 0;
1470 int i;
1471 s = store_get(size);
1472 for (i = 0; i < recipients_count; i++)
1473 {
1474 if (i != 0) s = string_cat(s, &size, &ptr, US", ", 2);
1475 s = string_cat(s, &size, &ptr, recipients_list[i].address,
1476 Ustrlen(recipients_list[i].address));
1477 }
1478 s[ptr] = 0; /* string_cat() leaves room */
1479 }
1480 return s;
8e669ac1 1481
5cb8cbc6
PH
1482 case vtype_pspace:
1483 {
1484 int inodes;
8e669ac1
PH
1485 sprintf(CS var_buffer, "%d",
1486 receive_statvfs(var_table[middle].value == (void *)TRUE, &inodes));
5cb8cbc6
PH
1487 }
1488 return var_buffer;
8e669ac1 1489
5cb8cbc6
PH
1490 case vtype_pinodes:
1491 {
1492 int inodes;
8e669ac1 1493 (void) receive_statvfs(var_table[middle].value == (void *)TRUE, &inodes);
5cb8cbc6
PH
1494 sprintf(CS var_buffer, "%d", inodes);
1495 }
1496 return var_buffer;
059ec3d9
PH
1497 }
1498 }
1499
1500return NULL; /* Unknown variable name */
1501}
1502
1503
1504
1505
1506/*************************************************
1507* Read and expand substrings *
1508*************************************************/
1509
1510/* This function is called to read and expand argument substrings for various
1511expansion items. Some have a minimum requirement that is less than the maximum;
1512in these cases, the first non-present one is set to NULL.
1513
1514Arguments:
1515 sub points to vector of pointers to set
1516 n maximum number of substrings
1517 m minimum required
1518 sptr points to current string pointer
1519 skipping the skipping flag
1520 check_end if TRUE, check for final '}'
1521 name name of item, for error message
1522
1523Returns: 0 OK; string pointer updated
1524 1 curly bracketing error (too few arguments)
1525 2 too many arguments (only if check_end is set); message set
1526 3 other error (expansion failure)
1527*/
1528
1529static int
1530read_subs(uschar **sub, int n, int m, uschar **sptr, BOOL skipping,
1531 BOOL check_end, uschar *name)
1532{
1533int i;
1534uschar *s = *sptr;
1535
1536while (isspace(*s)) s++;
1537for (i = 0; i < n; i++)
1538 {
1539 if (*s != '{')
1540 {
1541 if (i < m) return 1;
1542 sub[i] = NULL;
1543 break;
1544 }
1545 sub[i] = expand_string_internal(s+1, TRUE, &s, skipping);
1546 if (sub[i] == NULL) return 3;
1547 if (*s++ != '}') return 1;
1548 while (isspace(*s)) s++;
1549 }
1550if (check_end && *s++ != '}')
1551 {
1552 if (s[-1] == '{')
1553 {
1554 expand_string_message = string_sprintf("Too many arguments for \"%s\" "
1555 "(max is %d)", name, n);
1556 return 2;
1557 }
1558 return 1;
1559 }
1560
1561*sptr = s;
1562return 0;
1563}
1564
1565
1566
1567
1568/*************************************************
1569* Read and evaluate a condition *
1570*************************************************/
1571
1572/*
1573Arguments:
1574 s points to the start of the condition text
1575 yield points to a BOOL to hold the result of the condition test;
1576 if NULL, we are just reading through a condition that is
1577 part of an "or" combination to check syntax, or in a state
1578 where the answer isn't required
1579
1580Returns: a pointer to the first character after the condition, or
1581 NULL after an error
1582*/
1583
1584static uschar *
1585eval_condition(uschar *s, BOOL *yield)
1586{
1587BOOL testfor = TRUE;
1588BOOL tempcond, combined_cond;
1589BOOL *subcondptr;
1590int i, rc, cond_type, roffset;
1591int num[2];
1592struct stat statbuf;
1593uschar name[256];
1594uschar *sub[4];
1595
1596const pcre *re;
1597const uschar *rerror;
1598
1599for (;;)
1600 {
1601 while (isspace(*s)) s++;
1602 if (*s == '!') { testfor = !testfor; s++; } else break;
1603 }
1604
1605/* Numeric comparisons are symbolic */
1606
1607if (*s == '=' || *s == '>' || *s == '<')
1608 {
1609 int p = 0;
1610 name[p++] = *s++;
1611 if (*s == '=')
1612 {
1613 name[p++] = '=';
1614 s++;
1615 }
1616 name[p] = 0;
1617 }
1618
1619/* All other conditions are named */
1620
1621else s = read_name(name, 256, s, US"_");
1622
1623/* If we haven't read a name, it means some non-alpha character is first. */
1624
1625if (name[0] == 0)
1626 {
1627 expand_string_message = string_sprintf("condition name expected, "
1628 "but found \"%.16s\"", s);
1629 return NULL;
1630 }
1631
1632/* Find which condition we are dealing with, and switch on it */
1633
1634cond_type = chop_match(name, cond_table, sizeof(cond_table)/sizeof(uschar *));
1635switch(cond_type)
1636 {
9b4768fa
PH
1637 /* def: tests for a non-empty variable, or for the existence of a header. If
1638 yield == NULL we are in a skipping state, and don't care about the answer. */
059ec3d9
PH
1639
1640 case ECOND_DEF:
1641 if (*s != ':')
1642 {
1643 expand_string_message = US"\":\" expected after \"def\"";
1644 return NULL;
1645 }
1646
1647 s = read_name(name, 256, s+1, US"_");
1648
1649 /* Test for a header's existence */
1650
1651 if (Ustrncmp(name, "h_", 2) == 0 ||
1652 Ustrncmp(name, "rh_", 3) == 0 ||
1653 Ustrncmp(name, "bh_", 3) == 0 ||
1654 Ustrncmp(name, "header_", 7) == 0 ||
1655 Ustrncmp(name, "rheader_", 8) == 0 ||
1656 Ustrncmp(name, "bheader_", 8) == 0)
1657 {
1658 s = read_header_name(name, 256, s);
1659 if (yield != NULL) *yield =
1660 (find_header(name, TRUE, NULL, FALSE, NULL) != NULL) == testfor;
1661 }
1662
9b4768fa
PH
1663 /* Test for a variable's having a non-empty value. A non-existent variable
1664 causes an expansion failure. */
059ec3d9
PH
1665
1666 else
1667 {
1668 uschar *value = find_variable(name, TRUE, yield == NULL, NULL);
1669 if (value == NULL)
1670 {
1671 expand_string_message = (name[0] == 0)?
1672 string_sprintf("variable name omitted after \"def:\"") :
1673 string_sprintf("unknown variable \"%s\" after \"def:\"", name);
38a0a95f
PH
1674
1675 if (strict_acl_vars &&
1676 Ustrncmp(name, "acl_", 4) == 0 &&
1677 (name[4] == 'c' || name[4] == 'm'))
1678 expand_string_message = string_sprintf("%s (strict_acl_vars is set)",
1679 expand_string_message);
1680
059ec3d9
PH
1681 return NULL;
1682 }
9b4768fa 1683 if (yield != NULL) *yield = (value[0] != 0) == testfor;
059ec3d9
PH
1684 }
1685
1686 return s;
1687
1688
1689 /* first_delivery tests for first delivery attempt */
1690
1691 case ECOND_FIRST_DELIVERY:
1692 if (yield != NULL) *yield = deliver_firsttime == testfor;
1693 return s;
1694
1695
1696 /* queue_running tests for any process started by a queue runner */
1697
1698 case ECOND_QUEUE_RUNNING:
1699 if (yield != NULL) *yield = (queue_run_pid != (pid_t)0) == testfor;
1700 return s;
1701
1702
1703 /* exists: tests for file existence
1704 isip: tests for any IP address
1705 isip4: tests for an IPv4 address
1706 isip6: tests for an IPv6 address
1707 pam: does PAM authentication
1708 radius: does RADIUS authentication
1709 ldapauth: does LDAP authentication
1710 pwcheck: does Cyrus SASL pwcheck authentication
1711 */
1712
1713 case ECOND_EXISTS:
1714 case ECOND_ISIP:
1715 case ECOND_ISIP4:
1716 case ECOND_ISIP6:
1717 case ECOND_PAM:
1718 case ECOND_RADIUS:
1719 case ECOND_LDAPAUTH:
1720 case ECOND_PWCHECK:
1721
1722 while (isspace(*s)) s++;
1723 if (*s != '{') goto COND_FAILED_CURLY_START;
1724
1725 sub[0] = expand_string_internal(s+1, TRUE, &s, yield == NULL);
1726 if (sub[0] == NULL) return NULL;
1727 if (*s++ != '}') goto COND_FAILED_CURLY_END;
1728
1729 if (yield == NULL) return s; /* No need to run the test if skipping */
1730
1731 switch(cond_type)
1732 {
1733 case ECOND_EXISTS:
1734 if ((expand_forbid & RDO_EXISTS) != 0)
1735 {
1736 expand_string_message = US"File existence tests are not permitted";
1737 return NULL;
1738 }
1739 *yield = (Ustat(sub[0], &statbuf) == 0) == testfor;
1740 break;
1741
1742 case ECOND_ISIP:
1743 case ECOND_ISIP4:
1744 case ECOND_ISIP6:
1745 rc = string_is_ip_address(sub[0], NULL);
7e66e54d 1746 *yield = ((cond_type == ECOND_ISIP)? (rc != 0) :
059ec3d9
PH
1747 (cond_type == ECOND_ISIP4)? (rc == 4) : (rc == 6)) == testfor;
1748 break;
1749
1750 /* Various authentication tests - all optionally compiled */
1751
1752 case ECOND_PAM:
1753 #ifdef SUPPORT_PAM
1754 rc = auth_call_pam(sub[0], &expand_string_message);
1755 goto END_AUTH;
1756 #else
1757 goto COND_FAILED_NOT_COMPILED;
1758 #endif /* SUPPORT_PAM */
1759
1760 case ECOND_RADIUS:
1761 #ifdef RADIUS_CONFIG_FILE
1762 rc = auth_call_radius(sub[0], &expand_string_message);
1763 goto END_AUTH;
1764 #else
1765 goto COND_FAILED_NOT_COMPILED;
1766 #endif /* RADIUS_CONFIG_FILE */
1767
1768 case ECOND_LDAPAUTH:
1769 #ifdef LOOKUP_LDAP
1770 {
1771 /* Just to keep the interface the same */
1772 BOOL do_cache;
1773 int old_pool = store_pool;
1774 store_pool = POOL_SEARCH;
1775 rc = eldapauth_find((void *)(-1), NULL, sub[0], Ustrlen(sub[0]), NULL,
1776 &expand_string_message, &do_cache);
1777 store_pool = old_pool;
1778 }
1779 goto END_AUTH;
1780 #else
1781 goto COND_FAILED_NOT_COMPILED;
1782 #endif /* LOOKUP_LDAP */
1783
1784 case ECOND_PWCHECK:
1785 #ifdef CYRUS_PWCHECK_SOCKET
1786 rc = auth_call_pwcheck(sub[0], &expand_string_message);
1787 goto END_AUTH;
1788 #else
1789 goto COND_FAILED_NOT_COMPILED;
1790 #endif /* CYRUS_PWCHECK_SOCKET */
1791
1792 #if defined(SUPPORT_PAM) || defined(RADIUS_CONFIG_FILE) || \
1793 defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET)
1794 END_AUTH:
1795 if (rc == ERROR || rc == DEFER) return NULL;
1796 *yield = (rc == OK) == testfor;
1797 #endif
1798 }
1799 return s;
1800
1801
1802 /* saslauthd: does Cyrus saslauthd authentication. Four parameters are used:
1803
1804 ${if saslauthd {{username}{password}{service}{realm}} {yes}[no}}
1805
1806 However, the last two are optional. That is why the whole set is enclosed
1807 in their own set or braces. */
1808
1809 case ECOND_SASLAUTHD:
1810 #ifndef CYRUS_SASLAUTHD_SOCKET
1811 goto COND_FAILED_NOT_COMPILED;
1812 #else
1813 while (isspace(*s)) s++;
1814 if (*s++ != '{') goto COND_FAILED_CURLY_START;
1815 switch(read_subs(sub, 4, 2, &s, yield == NULL, TRUE, US"saslauthd"))
1816 {
1817 case 1: expand_string_message = US"too few arguments or bracketing "
1818 "error for saslauthd";
1819 case 2:
1820 case 3: return NULL;
1821 }
1822 if (sub[2] == NULL) sub[3] = NULL; /* realm if no service */
1823 if (yield != NULL)
1824 {
1825 int rc;
1826 rc = auth_call_saslauthd(sub[0], sub[1], sub[2], sub[3],
1827 &expand_string_message);
1828 if (rc == ERROR || rc == DEFER) return NULL;
1829 *yield = (rc == OK) == testfor;
1830 }
1831 return s;
1832 #endif /* CYRUS_SASLAUTHD_SOCKET */
1833
1834
1835 /* symbolic operators for numeric and string comparison, and a number of
1836 other operators, all requiring two arguments.
1837
1838 match: does a regular expression match and sets up the numerical
1839 variables if it succeeds
1840 match_address: matches in an address list
1841 match_domain: matches in a domain list
32d668a5 1842 match_ip: matches a host list that is restricted to IP addresses
059ec3d9
PH
1843 match_local_part: matches in a local part list
1844 crypteq: encrypts plaintext and compares against an encrypted text,
1845 using crypt(), crypt16(), MD5 or SHA-1
1846 */
1847
1848 case ECOND_MATCH:
1849 case ECOND_MATCH_ADDRESS:
1850 case ECOND_MATCH_DOMAIN:
32d668a5 1851 case ECOND_MATCH_IP:
059ec3d9
PH
1852 case ECOND_MATCH_LOCAL_PART:
1853 case ECOND_CRYPTEQ:
1854
1855 case ECOND_NUM_L: /* Numerical comparisons */
1856 case ECOND_NUM_LE:
1857 case ECOND_NUM_E:
1858 case ECOND_NUM_EE:
1859 case ECOND_NUM_G:
1860 case ECOND_NUM_GE:
1861
1862 case ECOND_STR_LT: /* String comparisons */
1863 case ECOND_STR_LTI:
1864 case ECOND_STR_LE:
1865 case ECOND_STR_LEI:
1866 case ECOND_STR_EQ:
1867 case ECOND_STR_EQI:
1868 case ECOND_STR_GT:
1869 case ECOND_STR_GTI:
1870 case ECOND_STR_GE:
1871 case ECOND_STR_GEI:
1872
1873 for (i = 0; i < 2; i++)
1874 {
1875 while (isspace(*s)) s++;
1876 if (*s != '{')
1877 {
1878 if (i == 0) goto COND_FAILED_CURLY_START;
1879 expand_string_message = string_sprintf("missing 2nd string in {} "
1880 "after \"%s\"", name);
1881 return NULL;
1882 }
1883 sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL);
1884 if (sub[i] == NULL) return NULL;
1885 if (*s++ != '}') goto COND_FAILED_CURLY_END;
1886
1887 /* Convert to numerical if required; we know that the names of all the
1888 conditions that compare numbers do not start with a letter. This just saves
1889 checking for them individually. */
1890
1891 if (!isalpha(name[0]))
1892 {
d45b1de8
PH
1893 num[i] = expand_string_integer(sub[i], FALSE);
1894 if (expand_string_message != NULL) return NULL;
059ec3d9
PH
1895 }
1896 }
1897
1898 /* Result not required */
1899
1900 if (yield == NULL) return s;
1901
1902 /* Do an appropriate comparison */
1903
1904 switch(cond_type)
1905 {
1906 case ECOND_NUM_E:
1907 case ECOND_NUM_EE:
1908 *yield = (num[0] == num[1]) == testfor;
1909 break;
1910
1911 case ECOND_NUM_G:
1912 *yield = (num[0] > num[1]) == testfor;
1913 break;
1914
1915 case ECOND_NUM_GE:
1916 *yield = (num[0] >= num[1]) == testfor;
1917 break;
1918
1919 case ECOND_NUM_L:
1920 *yield = (num[0] < num[1]) == testfor;
1921 break;
1922
1923 case ECOND_NUM_LE:
1924 *yield = (num[0] <= num[1]) == testfor;
1925 break;
1926
1927 case ECOND_STR_LT:
1928 *yield = (Ustrcmp(sub[0], sub[1]) < 0) == testfor;
1929 break;
1930
1931 case ECOND_STR_LTI:
1932 *yield = (strcmpic(sub[0], sub[1]) < 0) == testfor;
1933 break;
1934
1935 case ECOND_STR_LE:
1936 *yield = (Ustrcmp(sub[0], sub[1]) <= 0) == testfor;
1937 break;
1938
1939 case ECOND_STR_LEI:
1940 *yield = (strcmpic(sub[0], sub[1]) <= 0) == testfor;
1941 break;
1942
1943 case ECOND_STR_EQ:
1944 *yield = (Ustrcmp(sub[0], sub[1]) == 0) == testfor;
1945 break;
1946
1947 case ECOND_STR_EQI:
1948 *yield = (strcmpic(sub[0], sub[1]) == 0) == testfor;
1949 break;
1950
1951 case ECOND_STR_GT:
1952 *yield = (Ustrcmp(sub[0], sub[1]) > 0) == testfor;
1953 break;
1954
1955 case ECOND_STR_GTI:
1956 *yield = (strcmpic(sub[0], sub[1]) > 0) == testfor;
1957 break;
1958
1959 case ECOND_STR_GE:
1960 *yield = (Ustrcmp(sub[0], sub[1]) >= 0) == testfor;
1961 break;
1962
1963 case ECOND_STR_GEI:
1964 *yield = (strcmpic(sub[0], sub[1]) >= 0) == testfor;
1965 break;
1966
1967 case ECOND_MATCH: /* Regular expression match */
1968 re = pcre_compile(CS sub[1], PCRE_COPT, (const char **)&rerror, &roffset,
1969 NULL);
1970 if (re == NULL)
1971 {
1972 expand_string_message = string_sprintf("regular expression error in "
1973 "\"%s\": %s at offset %d", sub[1], rerror, roffset);
1974 return NULL;
1975 }
1976 *yield = regex_match_and_setup(re, sub[0], 0, -1) == testfor;
1977 break;
1978
1979 case ECOND_MATCH_ADDRESS: /* Match in an address list */
1980 rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0, NULL);
1981 goto MATCHED_SOMETHING;
1982
1983 case ECOND_MATCH_DOMAIN: /* Match in a domain list */
1984 rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
1985 MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
1986 goto MATCHED_SOMETHING;
1987
32d668a5 1988 case ECOND_MATCH_IP: /* Match IP address in a host list */
7e66e54d 1989 if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) == 0)
32d668a5
PH
1990 {
1991 expand_string_message = string_sprintf("\"%s\" is not an IP address",
1992 sub[0]);
1993 return NULL;
1994 }
1995 else
1996 {
1997 unsigned int *nullcache = NULL;
1998 check_host_block cb;
1999
2000 cb.host_name = US"";
2001 cb.host_address = sub[0];
2002
2003 /* If the host address starts off ::ffff: it is an IPv6 address in
2004 IPv4-compatible mode. Find the IPv4 part for checking against IPv4
2005 addresses. */
2006
2007 cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
2008 cb.host_address + 7 : cb.host_address;
2009
2010 rc = match_check_list(
2011 &sub[1], /* the list */
2012 0, /* separator character */
2013 &hostlist_anchor, /* anchor pointer */
2014 &nullcache, /* cache pointer */
2015 check_host, /* function for testing */
2016 &cb, /* argument for function */
2017 MCL_HOST, /* type of check */
2018 sub[0], /* text for debugging */
2019 NULL); /* where to pass back data */
2020 }
2021 goto MATCHED_SOMETHING;
2022
059ec3d9
PH
2023 case ECOND_MATCH_LOCAL_PART:
2024 rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
2025 MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
2026 /* Fall through */
9a26b6b2 2027 /* VVVVVVVVVVVV */
059ec3d9
PH
2028 MATCHED_SOMETHING:
2029 switch(rc)
2030 {
2031 case OK:
2032 *yield = testfor;
2033 break;
2034
2035 case FAIL:
2036 *yield = !testfor;
2037 break;
2038
2039 case DEFER:
2040 expand_string_message = string_sprintf("unable to complete match "
2041 "against \"%s\": %s", sub[1], search_error_message);
2042 return NULL;
2043 }
2044
2045 break;
2046
2047 /* Various "encrypted" comparisons. If the second string starts with
2048 "{" then an encryption type is given. Default to crypt() or crypt16()
2049 (build-time choice). */
2050
2051 case ECOND_CRYPTEQ:
2052 #ifndef SUPPORT_CRYPTEQ
2053 goto COND_FAILED_NOT_COMPILED;
2054 #else
2055 if (strncmpic(sub[1], US"{md5}", 5) == 0)
2056 {
2057 int sublen = Ustrlen(sub[1]+5);
2058 md5 base;
2059 uschar digest[16];
2060
2061 md5_start(&base);
2062 md5_end(&base, (uschar *)sub[0], Ustrlen(sub[0]), digest);
2063
2064 /* If the length that we are comparing against is 24, the MD5 digest
2065 is expressed as a base64 string. This is the way LDAP does it. However,
2066 some other software uses a straightforward hex representation. We assume
2067 this if the length is 32. Other lengths fail. */
2068
2069 if (sublen == 24)
2070 {
2071 uschar *coded = auth_b64encode((uschar *)digest, 16);
2072 DEBUG(D_auth) debug_printf("crypteq: using MD5+B64 hashing\n"
2073 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
2074 *yield = (Ustrcmp(coded, sub[1]+5) == 0) == testfor;
2075 }
2076 else if (sublen == 32)
2077 {
2078 int i;
2079 uschar coded[36];
2080 for (i = 0; i < 16; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
2081 coded[32] = 0;
2082 DEBUG(D_auth) debug_printf("crypteq: using MD5+hex hashing\n"
2083 " subject=%s\n crypted=%s\n", coded, sub[1]+5);
2084 *yield = (strcmpic(coded, sub[1]+5) == 0) == testfor;
2085 }
2086 else
2087 {
2088 DEBUG(D_auth) debug_printf("crypteq: length for MD5 not 24 or 32: "
2089 "fail\n crypted=%s\n", sub[1]+5);
2090 *yield = !testfor;
2091 }
2092 }
2093
2094 else if (strncmpic(sub[1], US"{sha1}", 6) == 0)
2095 {
2096 int sublen = Ustrlen(sub[1]+6);
2097 sha1 base;
2098 uschar digest[20];
2099
2100 sha1_start(&base);
2101 sha1_end(&base, (uschar *)sub[0], Ustrlen(sub[0]), digest);
2102
2103 /* If the length that we are comparing against is 28, assume the SHA1
2104 digest is expressed as a base64 string. If the length is 40, assume a
2105 straightforward hex representation. Other lengths fail. */
2106
2107 if (sublen == 28)
2108 {
2109 uschar *coded = auth_b64encode((uschar *)digest, 20);
2110 DEBUG(D_auth) debug_printf("crypteq: using SHA1+B64 hashing\n"
2111 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
2112 *yield = (Ustrcmp(coded, sub[1]+6) == 0) == testfor;
2113 }
2114 else if (sublen == 40)
2115 {
2116 int i;
2117 uschar coded[44];
2118 for (i = 0; i < 20; i++) sprintf(CS (coded+2*i), "%02X", digest[i]);
2119 coded[40] = 0;
2120 DEBUG(D_auth) debug_printf("crypteq: using SHA1+hex hashing\n"
2121 " subject=%s\n crypted=%s\n", coded, sub[1]+6);
2122 *yield = (strcmpic(coded, sub[1]+6) == 0) == testfor;
2123 }
2124 else
2125 {
2126 DEBUG(D_auth) debug_printf("crypteq: length for SHA-1 not 28 or 40: "
2127 "fail\n crypted=%s\n", sub[1]+6);
2128 *yield = !testfor;
2129 }
2130 }
2131
2132 else /* {crypt} or {crypt16} and non-{ at start */
2133 {
2134 int which = 0;
2135 uschar *coded;
2136
2137 if (strncmpic(sub[1], US"{crypt}", 7) == 0)
2138 {
2139 sub[1] += 7;
2140 which = 1;
2141 }
2142 else if (strncmpic(sub[1], US"{crypt16}", 9) == 0)
2143 {
2144 sub[1] += 9;
2145 which = 2;
2146 }
2147 else if (sub[1][0] == '{')
2148 {
2149 expand_string_message = string_sprintf("unknown encryption mechanism "
2150 "in \"%s\"", sub[1]);
2151 return NULL;
2152 }
2153
2154 switch(which)
2155 {
2156 case 0: coded = US DEFAULT_CRYPT(CS sub[0], CS sub[1]); break;
2157 case 1: coded = US crypt(CS sub[0], CS sub[1]); break;
2158 default: coded = US crypt16(CS sub[0], CS sub[1]); break;
2159 }
2160
2161 #define STR(s) # s
2162 #define XSTR(s) STR(s)
2163 DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
2164 " subject=%s\n crypted=%s\n",
2165 (which == 0)? XSTR(DEFAULT_CRYPT) : (which == 1)? "crypt" : "crypt16",
2166 coded, sub[1]);
2167 #undef STR
2168 #undef XSTR
2169
2170 /* If the encrypted string contains fewer than two characters (for the
2171 salt), force failure. Otherwise we get false positives: with an empty
2172 string the yield of crypt() is an empty string! */
2173
2174 *yield = (Ustrlen(sub[1]) < 2)? !testfor :
2175 (Ustrcmp(coded, sub[1]) == 0) == testfor;
2176 }
2177 break;
2178 #endif /* SUPPORT_CRYPTEQ */
2179 } /* Switch for comparison conditions */
2180
2181 return s; /* End of comparison conditions */
2182
2183
2184 /* and/or: computes logical and/or of several conditions */
2185
2186 case ECOND_AND:
2187 case ECOND_OR:
2188 subcondptr = (yield == NULL)? NULL : &tempcond;
2189 combined_cond = (cond_type == ECOND_AND);
2190
2191 while (isspace(*s)) s++;
2192 if (*s++ != '{') goto COND_FAILED_CURLY_START;
2193
2194 for (;;)
2195 {
2196 while (isspace(*s)) s++;
2197 if (*s == '}') break;
2198 if (*s != '{')
2199 {
2200 expand_string_message = string_sprintf("each subcondition "
2201 "inside an \"%s{...}\" condition must be in its own {}", name);
2202 return NULL;
2203 }
2204
2205 s = eval_condition(s+1, subcondptr);
2206 if (s == NULL)
2207 {
2208 expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
2209 expand_string_message, name);
2210 return NULL;
2211 }
2212 while (isspace(*s)) s++;
2213
2214 if (*s++ != '}')
2215 {
2216 expand_string_message = string_sprintf("missing } at end of condition "
2217 "inside \"%s\" group", name);
2218 return NULL;
2219 }
2220
2221 if (yield != NULL)
2222 {
2223 if (cond_type == ECOND_AND)
2224 {
2225 combined_cond &= tempcond;
2226 if (!combined_cond) subcondptr = NULL; /* once false, don't */
2227 } /* evaluate any more */
2228 else
2229 {
2230 combined_cond |= tempcond;
2231 if (combined_cond) subcondptr = NULL; /* once true, don't */
2232 } /* evaluate any more */
2233 }
2234 }
2235
2236 if (yield != NULL) *yield = (combined_cond == testfor);
2237 return ++s;
2238
2239
2240 /* Unknown condition */
2241
2242 default:
2243 expand_string_message = string_sprintf("unknown condition \"%s\"", name);
2244 return NULL;
2245 } /* End switch on condition type */
2246
2247/* Missing braces at start and end of data */
2248
2249COND_FAILED_CURLY_START:
2250expand_string_message = string_sprintf("missing { after \"%s\"", name);
2251return NULL;
2252
2253COND_FAILED_CURLY_END:
2254expand_string_message = string_sprintf("missing } at end of \"%s\" condition",
2255 name);
2256return NULL;
2257
2258/* A condition requires code that is not compiled */
2259
2260#if !defined(SUPPORT_PAM) || !defined(RADIUS_CONFIG_FILE) || \
2261 !defined(LOOKUP_LDAP) || !defined(CYRUS_PWCHECK_SOCKET) || \
2262 !defined(SUPPORT_CRYPTEQ) || !defined(CYRUS_SASLAUTHD_SOCKET)
2263COND_FAILED_NOT_COMPILED:
2264expand_string_message = string_sprintf("support for \"%s\" not compiled",
2265 name);
2266return NULL;
2267#endif
2268}
2269
2270
2271
2272
2273/*************************************************
2274* Save numerical variables *
2275*************************************************/
2276
2277/* This function is called from items such as "if" that want to preserve and
2278restore the numbered variables.
2279
2280Arguments:
2281 save_expand_string points to an array of pointers to set
2282 save_expand_nlength points to an array of ints for the lengths
2283
2284Returns: the value of expand max to save
2285*/
2286
2287static int
2288save_expand_strings(uschar **save_expand_nstring, int *save_expand_nlength)
2289{
2290int i;
2291for (i = 0; i <= expand_nmax; i++)
2292 {
2293 save_expand_nstring[i] = expand_nstring[i];
2294 save_expand_nlength[i] = expand_nlength[i];
2295 }
2296return expand_nmax;
2297}
2298
2299
2300
2301/*************************************************
2302* Restore numerical variables *
2303*************************************************/
2304
2305/* This function restored saved values of numerical strings.
2306
2307Arguments:
2308 save_expand_nmax the number of strings to restore
2309 save_expand_string points to an array of pointers
2310 save_expand_nlength points to an array of ints
2311
2312Returns: nothing
2313*/
2314
2315static void
2316restore_expand_strings(int save_expand_nmax, uschar **save_expand_nstring,
2317 int *save_expand_nlength)
2318{
2319int i;
2320expand_nmax = save_expand_nmax;
2321for (i = 0; i <= expand_nmax; i++)
2322 {
2323 expand_nstring[i] = save_expand_nstring[i];
2324 expand_nlength[i] = save_expand_nlength[i];
2325 }
2326}
2327
2328
2329
2330
2331
2332/*************************************************
2333* Handle yes/no substrings *
2334*************************************************/
2335
2336/* This function is used by ${if}, ${lookup} and ${extract} to handle the
2337alternative substrings that depend on whether or not the condition was true,
2338or the lookup or extraction succeeded. The substrings always have to be
2339expanded, to check their syntax, but "skipping" is set when the result is not
2340needed - this avoids unnecessary nested lookups.
2341
2342Arguments:
2343 skipping TRUE if we were skipping when this item was reached
2344 yes TRUE if the first string is to be used, else use the second
2345 save_lookup a value to put back into lookup_value before the 2nd expansion
2346 sptr points to the input string pointer
2347 yieldptr points to the output string pointer
2348 sizeptr points to the output string size
2349 ptrptr points to the output string pointer
2350 type "lookup" or "if" or "extract" or "run", for error message
2351
2352Returns: 0 OK; lookup_value has been reset to save_lookup
2353 1 expansion failed
2354 2 expansion failed because of bracketing error
2355*/
2356
2357static int
2358process_yesno(BOOL skipping, BOOL yes, uschar *save_lookup, uschar **sptr,
2359 uschar **yieldptr, int *sizeptr, int *ptrptr, uschar *type)
2360{
2361int rc = 0;
2362uschar *s = *sptr; /* Local value */
2363uschar *sub1, *sub2;
2364
2365/* If there are no following strings, we substitute the contents of $value for
063b1e99 2366lookups and for extractions in the success case. For the ${if item, the string
8e669ac1 2367"true" is substituted. In the fail case, nothing is substituted for all three
063b1e99 2368items. */
059ec3d9
PH
2369
2370while (isspace(*s)) s++;
2371if (*s == '}')
2372 {
063b1e99
PH
2373 if (type[0] == 'i')
2374 {
8e669ac1 2375 if (yes) *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, US"true", 4);
063b1e99
PH
2376 }
2377 else
8e669ac1 2378 {
063b1e99
PH
2379 if (yes && lookup_value != NULL)
2380 *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value,
2381 Ustrlen(lookup_value));
2382 lookup_value = save_lookup;
2383 }
059ec3d9
PH
2384 s++;
2385 goto RETURN;
2386 }
2387
9b4768fa
PH
2388/* The first following string must be braced. */
2389
2390if (*s++ != '{') goto FAILED_CURLY;
2391
059ec3d9
PH
2392/* Expand the first substring. Forced failures are noticed only if we actually
2393want this string. Set skipping in the call in the fail case (this will always
2394be the case if we were already skipping). */
2395
9b4768fa 2396sub1 = expand_string_internal(s, TRUE, &s, !yes);
059ec3d9
PH
2397if (sub1 == NULL && (yes || !expand_string_forcedfail)) goto FAILED;
2398expand_string_forcedfail = FALSE;
2399if (*s++ != '}') goto FAILED_CURLY;
2400
2401/* If we want the first string, add it to the output */
2402
2403if (yes)
2404 *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, sub1, Ustrlen(sub1));
2405
2406/* If this is called from a lookup or an extract, we want to restore $value to
2407what it was at the start of the item, so that it has this value during the
d20976dc
PH
2408second string expansion. For the call from "if" or "run" to this function,
2409save_lookup is set to lookup_value, so that this statement does nothing. */
059ec3d9
PH
2410
2411lookup_value = save_lookup;
2412
2413/* There now follows either another substring, or "fail", or nothing. This
2414time, forced failures are noticed only if we want the second string. We must
2415set skipping in the nested call if we don't want this string, or if we were
2416already skipping. */
2417
2418while (isspace(*s)) s++;
2419if (*s == '{')
2420 {
2421 sub2 = expand_string_internal(s+1, TRUE, &s, yes || skipping);
2422 if (sub2 == NULL && (!yes || !expand_string_forcedfail)) goto FAILED;
2423 expand_string_forcedfail = FALSE;
2424 if (*s++ != '}') goto FAILED_CURLY;
2425
2426 /* If we want the second string, add it to the output */
2427
2428 if (!yes)
2429 *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, sub2, Ustrlen(sub2));
2430 }
2431
2432/* If there is no second string, but the word "fail" is present when the use of
2433the second string is wanted, set a flag indicating it was a forced failure
2434rather than a syntactic error. Swallow the terminating } in case this is nested
2435inside another lookup or if or extract. */
2436
2437else if (*s != '}')
2438 {
2439 uschar name[256];
2440 s = read_name(name, sizeof(name), s, US"_");
2441 if (Ustrcmp(name, "fail") == 0)
2442 {
2443 if (!yes && !skipping)
2444 {
2445 while (isspace(*s)) s++;
2446 if (*s++ != '}') goto FAILED_CURLY;
2447 expand_string_message =
2448 string_sprintf("\"%s\" failed and \"fail\" requested", type);
2449 expand_string_forcedfail = TRUE;
2450 goto FAILED;
2451 }
2452 }
2453 else
2454 {
2455 expand_string_message =
2456 string_sprintf("syntax error in \"%s\" item - \"fail\" expected", type);
2457 goto FAILED;
2458 }
2459 }
2460
2461/* All we have to do now is to check on the final closing brace. */
2462
2463while (isspace(*s)) s++;
2464if (*s++ == '}') goto RETURN;
2465
2466/* Get here if there is a bracketing failure */
2467
2468FAILED_CURLY:
2469rc++;
2470
2471/* Get here for other failures */
2472
2473FAILED:
2474rc++;
2475
2476/* Update the input pointer value before returning */
2477
2478RETURN:
2479*sptr = s;
2480return rc;
2481}
2482
2483
2484
2485
059ec3d9
PH
2486/*************************************************
2487* Handle MD5 or SHA-1 computation for HMAC *
2488*************************************************/
2489
2490/* These are some wrapping functions that enable the HMAC code to be a bit
2491cleaner. A good compiler will spot the tail recursion.
2492
2493Arguments:
2494 type HMAC_MD5 or HMAC_SHA1
2495 remaining are as for the cryptographic hash functions
2496
2497Returns: nothing
2498*/
2499
2500static void
2501chash_start(int type, void *base)
2502{
2503if (type == HMAC_MD5)
2504 md5_start((md5 *)base);
2505else
2506 sha1_start((sha1 *)base);
2507}
2508
2509static void
2510chash_mid(int type, void *base, uschar *string)
2511{
2512if (type == HMAC_MD5)
2513 md5_mid((md5 *)base, string);
2514else
2515 sha1_mid((sha1 *)base, string);
2516}
2517
2518static void
2519chash_end(int type, void *base, uschar *string, int length, uschar *digest)
2520{
2521if (type == HMAC_MD5)
2522 md5_end((md5 *)base, string, length, digest);
2523else
2524 sha1_end((sha1 *)base, string, length, digest);
2525}
2526
2527
2528
2529
2530
1549ea3b
PH
2531/********************************************************
2532* prvs: Get last three digits of days since Jan 1, 1970 *
2533********************************************************/
2534
2535/* This is needed to implement the "prvs" BATV reverse
2536 path signing scheme
2537
2538Argument: integer "days" offset to add or substract to
2539 or from the current number of days.
2540
2541Returns: pointer to string containing the last three
2542 digits of the number of days since Jan 1, 1970,
2543 modified by the offset argument, NULL if there
2544 was an error in the conversion.
2545
2546*/
2547
2548static uschar *
2549prvs_daystamp(int day_offset)
2550{
a86229cf
PH
2551uschar *days = store_get(32); /* Need at least 24 for cases */
2552(void)string_format(days, 32, TIME_T_FMT, /* where TIME_T_FMT is %lld */
1549ea3b 2553 (time(NULL) + day_offset*86400)/86400);
e169f567 2554return (Ustrlen(days) >= 3) ? &days[Ustrlen(days)-3] : US"100";
1549ea3b
PH
2555}
2556
2557
2558
2559/********************************************************
2560* prvs: perform HMAC-SHA1 computation of prvs bits *
2561********************************************************/
2562
2563/* This is needed to implement the "prvs" BATV reverse
2564 path signing scheme
2565
2566Arguments:
2567 address RFC2821 Address to use
2568 key The key to use (must be less than 64 characters
2569 in size)
2570 key_num Single-digit key number to use. Defaults to
2571 '0' when NULL.
2572
2573Returns: pointer to string containing the first three
2574 bytes of the final hash in hex format, NULL if
2575 there was an error in the process.
2576*/
2577
2578static uschar *
2579prvs_hmac_sha1(uschar *address, uschar *key, uschar *key_num, uschar *daystamp)
2580{
2581uschar *hash_source, *p;
2582int size = 0,offset = 0,i;
2583sha1 sha1_base;
2584void *use_base = &sha1_base;
2585uschar innerhash[20];
2586uschar finalhash[20];
2587uschar innerkey[64];
2588uschar outerkey[64];
2589uschar *finalhash_hex = store_get(40);
2590
2591if (key_num == NULL)
2592 key_num = US"0";
2593
2594if (Ustrlen(key) > 64)
2595 return NULL;
2596
2597hash_source = string_cat(NULL,&size,&offset,key_num,1);
2598string_cat(hash_source,&size,&offset,daystamp,3);
2599string_cat(hash_source,&size,&offset,address,Ustrlen(address));
2600hash_source[offset] = '\0';
2601
2602DEBUG(D_expand) debug_printf("prvs: hash source is '%s'\n", hash_source);
2603
2604memset(innerkey, 0x36, 64);
2605memset(outerkey, 0x5c, 64);
2606
2607for (i = 0; i < Ustrlen(key); i++)
2608 {
2609 innerkey[i] ^= key[i];
2610 outerkey[i] ^= key[i];
2611 }
2612
2613chash_start(HMAC_SHA1, use_base);
2614chash_mid(HMAC_SHA1, use_base, innerkey);
2615chash_end(HMAC_SHA1, use_base, hash_source, offset, innerhash);
2616
2617chash_start(HMAC_SHA1, use_base);
2618chash_mid(HMAC_SHA1, use_base, outerkey);
2619chash_end(HMAC_SHA1, use_base, innerhash, 20, finalhash);
2620
2621p = finalhash_hex;
2622for (i = 0; i < 3; i++)
2623 {
2624 *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
2625 *p++ = hex_digits[finalhash[i] & 0x0f];
2626 }
2627*p = '\0';
2628
2629return finalhash_hex;
2630}
2631
2632
2633
2634
059ec3d9
PH
2635/*************************************************
2636* Join a file onto the output string *
2637*************************************************/
2638
2639/* This is used for readfile and after a run expansion. It joins the contents
2640of a file onto the output string, globally replacing newlines with a given
2641string (optionally). The file is closed at the end.
2642
2643Arguments:
2644 f the FILE
2645 yield pointer to the expandable string
2646 sizep pointer to the current size
2647 ptrp pointer to the current position
2648 eol newline replacement string, or NULL
2649
2650Returns: new value of string pointer
2651*/
2652
2653static uschar *
2654cat_file(FILE *f, uschar *yield, int *sizep, int *ptrp, uschar *eol)
2655{
2656int eollen;
2657uschar buffer[1024];
2658
2659eollen = (eol == NULL)? 0 : Ustrlen(eol);
2660
2661while (Ufgets(buffer, sizeof(buffer), f) != NULL)
2662 {
2663 int len = Ustrlen(buffer);
2664 if (eol != NULL && buffer[len-1] == '\n') len--;
2665 yield = string_cat(yield, sizep, ptrp, buffer, len);
2666 if (buffer[len] != 0)
2667 yield = string_cat(yield, sizep, ptrp, eol, eollen);
2668 }
2669
2670if (yield != NULL) yield[*ptrp] = 0;
2671
2672return yield;
2673}
2674
2675
2676
2677
2678/*************************************************
2679* Evaluate numeric expression *
2680*************************************************/
2681
2682/* This is a set of mutually recursive functions that evaluate a simple
2683arithmetic expression involving only + - * / and parentheses. The only one that
2684is called from elsewhere is eval_expr, whose interface is:
2685
2686Arguments:
2687 sptr pointer to the pointer to the string - gets updated
2688 decimal TRUE if numbers are to be assumed decimal
2689 error pointer to where to put an error message - must be NULL on input
2690 endket TRUE if ')' must terminate - FALSE for external call
2691
2692
2693Returns: on success: the value of the expression, with *error still NULL
2694 on failure: an undefined value, with *error = a message
2695*/
2696
2697static int eval_sumterm(uschar **, BOOL, uschar **);
2698
2699static int
2700eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket)
2701{
2702uschar *s = *sptr;
2703int x = eval_sumterm(&s, decimal, error);
2704if (*error == NULL)
2705 {
2706 while (*s == '+' || *s == '-')
2707 {
2708 int op = *s++;
2709 int y = eval_sumterm(&s, decimal, error);
2710 if (*error != NULL) break;
2711 if (op == '+') x += y; else x -= y;
2712 }
2713 if (*error == NULL)
2714 {
2715 if (endket)
2716 {
2717 if (*s != ')')
2718 *error = US"expecting closing parenthesis";
2719 else
2720 while (isspace(*(++s)));
2721 }
2722 else if (*s != 0) *error = US"expecting + or -";
2723 }
2724 }
2725
2726*sptr = s;
2727return x;
2728}
2729
2730static int
2731eval_term(uschar **sptr, BOOL decimal, uschar **error)
2732{
2733register int c;
2734int n;
2735uschar *s = *sptr;
2736while (isspace(*s)) s++;
2737c = *s;
2738if (isdigit(c) || ((c == '-' || c == '+') && isdigit(s[1])))
2739 {
2740 int count;
2741 (void)sscanf(CS s, (decimal? "%d%n" : "%i%n"), &n, &count);
2742 s += count;
2743 if (tolower(*s) == 'k') { n *= 1024; s++; }
2744 else if (tolower(*s) == 'm') { n *= 1024*1024; s++; }
2745 while (isspace (*s)) s++;
2746 }
2747else if (c == '(')
2748 {
2749 s++;
2750 n = eval_expr(&s, decimal, error, 1);
2751 }
2752else
2753 {
2754 *error = US"expecting number or opening parenthesis";
2755 n = 0;
2756 }
2757*sptr = s;
2758return n;
2759}
2760
2761static int eval_sumterm(uschar **sptr, BOOL decimal, uschar **error)
2762{
2763uschar *s = *sptr;
2764int x = eval_term(&s, decimal, error);
2765if (*error == NULL)
2766 {
5591031b 2767 while (*s == '*' || *s == '/' || *s == '%')
059ec3d9
PH
2768 {
2769 int op = *s++;
2770 int y = eval_term(&s, decimal, error);
2771 if (*error != NULL) break;
5591031b
PH
2772 if (op == '*') x *= y;
2773 else if (op == '/') x /= y;
2774 else x %= y;
059ec3d9
PH
2775 }
2776 }
2777*sptr = s;
2778return x;
2779}
2780
2781
2782
2783
2784/*************************************************
2785* Expand string *
2786*************************************************/
2787
2788/* Returns either an unchanged string, or the expanded string in stacking pool
2789store. Interpreted sequences are:
2790
2791 \... normal escaping rules
2792 $name substitutes the variable
2793 ${name} ditto
2794 ${op:string} operates on the expanded string value
2795 ${item{arg1}{arg2}...} expands the args and then does the business
2796 some literal args are not enclosed in {}
2797
2798There are now far too many operators and item types to make it worth listing
2799them here in detail any more.
2800
2801We use an internal routine recursively to handle embedded substrings. The
2802external function follows. The yield is NULL if the expansion failed, and there
2803are two cases: if something collapsed syntactically, or if "fail" was given
2804as the action on a lookup failure. These can be distinguised by looking at the
2805variable expand_string_forcedfail, which is TRUE in the latter case.
2806
2807The skipping flag is set true when expanding a substring that isn't actually
2808going to be used (after "if" or "lookup") and it prevents lookups from
2809happening lower down.
2810
2811Store usage: At start, a store block of the length of the input plus 64
2812is obtained. This is expanded as necessary by string_cat(), which might have to
2813get a new block, or might be able to expand the original. At the end of the
2814function we can release any store above that portion of the yield block that
2815was actually used. In many cases this will be optimal.
2816
2817However: if the first item in the expansion is a variable name or header name,
2818we reset the store before processing it; if the result is in fresh store, we
2819use that without copying. This is helpful for expanding strings like
2820$message_headers which can get very long.
2821
2822Arguments:
2823 string the string to be expanded
2824 ket_ends true if expansion is to stop at }
2825 left if not NULL, a pointer to the first character after the
2826 expansion is placed here (typically used with ket_ends)
2827 skipping TRUE for recursive calls when the value isn't actually going
2828 to be used (to allow for optimisation)
2829
2830Returns: NULL if expansion fails:
2831 expand_string_forcedfail is set TRUE if failure was forced
2832 expand_string_message contains a textual error message
2833 a pointer to the expanded string on success
2834*/
2835
2836static uschar *
2837expand_string_internal(uschar *string, BOOL ket_ends, uschar **left,
2838 BOOL skipping)
2839{
2840int ptr = 0;
2841int size = Ustrlen(string)+ 64;
2842int item_type;
2843uschar *yield = store_get(size);
2844uschar *s = string;
2845uschar *save_expand_nstring[EXPAND_MAXN+1];
2846int save_expand_nlength[EXPAND_MAXN+1];
2847
2848expand_string_forcedfail = FALSE;
2849expand_string_message = US"";
2850
2851while (*s != 0)
2852 {
2853 uschar *value;
2854 uschar name[256];
2855
2856 /* \ escapes the next character, which must exist, or else
2857 the expansion fails. There's a special escape, \N, which causes
2858 copying of the subject verbatim up to the next \N. Otherwise,
2859 the escapes are the standard set. */
2860
2861 if (*s == '\\')
2862 {
2863 if (s[1] == 0)
2864 {
2865 expand_string_message = US"\\ at end of string";
2866 goto EXPAND_FAILED;
2867 }
2868
2869 if (s[1] == 'N')
2870 {
2871 uschar *t = s + 2;
2872 for (s = t; *s != 0; s++) if (*s == '\\' && s[1] == 'N') break;
2873 yield = string_cat(yield, &size, &ptr, t, s - t);
2874 if (*s != 0) s += 2;
2875 }
2876
2877 else
2878 {
2879 uschar ch[1];
2880 ch[0] = string_interpret_escape(&s);
2881 s++;
2882 yield = string_cat(yield, &size, &ptr, ch, 1);
2883 }
2884
2885 continue;
2886 }
2887
2888 /* Anything other than $ is just copied verbatim, unless we are
2889 looking for a terminating } character. */
2890
2891 if (ket_ends && *s == '}') break;
2892
2893 if (*s != '$')
2894 {
2895 yield = string_cat(yield, &size, &ptr, s++, 1);
2896 continue;
2897 }
2898
2899 /* No { after the $ - must be a plain name or a number for string
2900 match variable. There has to be a fudge for variables that are the
2901 names of header fields preceded by "$header_" because header field
2902 names can contain any printing characters except space and colon.
2903 For those that don't like typing this much, "$h_" is a synonym for
2904 "$header_". A non-existent header yields a NULL value; nothing is
2905 inserted. */
2906
2907 if (isalpha((*(++s))))
2908 {
2909 int len;
2910 int newsize = 0;
2911
2912 s = read_name(name, sizeof(name), s, US"_");
2913
2914 /* If this is the first thing to be expanded, release the pre-allocated
2915 buffer. */
2916
2917 if (ptr == 0 && yield != NULL)
2918 {
2919 store_reset(yield);
2920 yield = NULL;
2921 size = 0;
2922 }
2923
2924 /* Header */
2925
2926 if (Ustrncmp(name, "h_", 2) == 0 ||
2927 Ustrncmp(name, "rh_", 3) == 0 ||
2928 Ustrncmp(name, "bh_", 3) == 0 ||
2929 Ustrncmp(name, "header_", 7) == 0 ||
2930 Ustrncmp(name, "rheader_", 8) == 0 ||
2931 Ustrncmp(name, "bheader_", 8) == 0)
2932 {
2933 BOOL want_raw = (name[0] == 'r')? TRUE : FALSE;
2934 uschar *charset = (name[0] == 'b')? NULL : headers_charset;
2935 s = read_header_name(name, sizeof(name), s);
2936 value = find_header(name, FALSE, &newsize, want_raw, charset);
2937
2938 /* If we didn't find the header, and the header contains a closing brace
2939 characters, this may be a user error where the terminating colon
2940 has been omitted. Set a flag to adjust the error message in this case.
2941 But there is no error here - nothing gets inserted. */
2942
2943 if (value == NULL)
2944 {
2945 if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
2946 continue;
2947 }
2948 }
2949
2950 /* Variable */
2951
2952 else
2953 {
2954 value = find_variable(name, FALSE, skipping, &newsize);
2955 if (value == NULL)
2956 {
2957 expand_string_message =
2958 string_sprintf("unknown variable name \"%s\"", name);
38a0a95f
PH
2959
2960 if (strict_acl_vars &&
2961 Ustrncmp(name, "acl_", 4) == 0 &&
2962 (name[4] == 'c' || name[4] == 'm'))
2963 expand_string_message = string_sprintf("%s (strict_acl_vars is set)",
2964 expand_string_message);
2965
059ec3d9
PH
2966 goto EXPAND_FAILED;
2967 }
2968 }
2969
2970 /* If the data is known to be in a new buffer, newsize will be set to the
2971 size of that buffer. If this is the first thing in an expansion string,
2972 yield will be NULL; just point it at the new store instead of copying. Many
2973 expansion strings contain just one reference, so this is a useful
2974 optimization, especially for humungous headers. */
2975
2976 len = Ustrlen(value);
2977 if (yield == NULL && newsize != 0)
2978 {
2979 yield = value;
2980 size = newsize;
2981 ptr = len;
2982 }
2983 else yield = string_cat(yield, &size, &ptr, value, len);
2984
2985 continue;
2986 }
2987
2988 if (isdigit(*s))
2989 {
2990 int n;
2991 s = read_number(&n, s);
2992 if (n >= 0 && n <= expand_nmax)
2993 yield = string_cat(yield, &size, &ptr, expand_nstring[n],
2994 expand_nlength[n]);
2995 continue;
2996 }
2997
2998 /* Otherwise, if there's no '{' after $ it's an error. */
2999
3000 if (*s != '{')
3001 {
3002 expand_string_message = US"$ not followed by letter, digit, or {";
3003 goto EXPAND_FAILED;
3004 }
3005
3006 /* After { there can be various things, but they all start with
3007 an initial word, except for a number for a string match variable. */
3008
3009 if (isdigit((*(++s))))
3010 {
3011 int n;
3012 s = read_number(&n, s);
3013 if (*s++ != '}')
3014 {
3015 expand_string_message = US"} expected after number";
3016 goto EXPAND_FAILED;
3017 }
3018 if (n >= 0 && n <= expand_nmax)
3019 yield = string_cat(yield, &size, &ptr, expand_nstring[n],
3020 expand_nlength[n]);
3021 continue;
3022 }
3023
3024 if (!isalpha(*s))
3025 {
3026 expand_string_message = US"letter or digit expected after ${";
3027 goto EXPAND_FAILED;
3028 }
3029
3030 /* Allow "-" in names to cater for substrings with negative
3031 arguments. Since we are checking for known names after { this is
3032 OK. */
3033
3034 s = read_name(name, sizeof(name), s, US"_-");
3035 item_type = chop_match(name, item_table, sizeof(item_table)/sizeof(uschar *));
3036
3037 switch(item_type)
3038 {
3039 /* Handle conditionals - preserve the values of the numerical expansion
3040 variables in case they get changed by a regular expression match in the
3041 condition. If not, they retain their external settings. At the end
3042 of this "if" section, they get restored to their previous values. */
3043
3044 case EITEM_IF:
3045 {
3046 BOOL cond = FALSE;
3047 uschar *next_s;
3048 int save_expand_nmax =
3049 save_expand_strings(save_expand_nstring, save_expand_nlength);
3050
3051 while (isspace(*s)) s++;
3052 next_s = eval_condition(s, skipping? NULL : &cond);
3053 if (next_s == NULL) goto EXPAND_FAILED; /* message already set */
3054
3055 DEBUG(D_expand)
3056 debug_printf("condition: %.*s\n result: %s\n", (int)(next_s - s), s,
3057 cond? "true" : "false");
3058
3059 s = next_s;
3060
3061 /* The handling of "yes" and "no" result strings is now in a separate
3062 function that is also used by ${lookup} and ${extract} and ${run}. */
3063
3064 switch(process_yesno(
3065 skipping, /* were previously skipping */
3066 cond, /* success/failure indicator */
3067 lookup_value, /* value to reset for string2 */
3068 &s, /* input pointer */
3069 &yield, /* output pointer */
3070 &size, /* output size */
3071 &ptr, /* output current point */
3072 US"if")) /* condition type */
3073 {
3074 case 1: goto EXPAND_FAILED; /* when all is well, the */
3075 case 2: goto EXPAND_FAILED_CURLY; /* returned value is 0 */
3076 }
3077
3078 /* Restore external setting of expansion variables for continuation
3079 at this level. */
3080
3081 restore_expand_strings(save_expand_nmax, save_expand_nstring,
3082 save_expand_nlength);
3083 continue;
3084 }
3085
3086 /* Handle database lookups unless locked out. If "skipping" is TRUE, we are
3087 expanding an internal string that isn't actually going to be used. All we
3088 need to do is check the syntax, so don't do a lookup at all. Preserve the
3089 values of the numerical expansion variables in case they get changed by a
3090 partial lookup. If not, they retain their external settings. At the end
3091 of this "lookup" section, they get restored to their previous values. */
3092
3093 case EITEM_LOOKUP:
3094 {
3095 int stype, partial, affixlen, starflags;
3096 int expand_setup = 0;
3097 int nameptr = 0;
3098 uschar *key, *filename, *affix;
3099 uschar *save_lookup_value = lookup_value;
3100 int save_expand_nmax =
3101 save_expand_strings(save_expand_nstring, save_expand_nlength);
3102
3103 if ((expand_forbid & RDO_LOOKUP) != 0)
3104 {
3105 expand_string_message = US"lookup expansions are not permitted";
3106 goto EXPAND_FAILED;
3107 }
3108
3109 /* Get the key we are to look up for single-key+file style lookups.
3110 Otherwise set the key NULL pro-tem. */
3111
3112 while (isspace(*s)) s++;
3113 if (*s == '{')
3114 {
3115 key = expand_string_internal(s+1, TRUE, &s, skipping);
3116 if (key == NULL) goto EXPAND_FAILED;
3117 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3118 while (isspace(*s)) s++;
3119 }
3120 else key = NULL;
3121
3122 /* Find out the type of database */
3123
3124 if (!isalpha(*s))
3125 {
3126 expand_string_message = US"missing lookup type";
3127 goto EXPAND_FAILED;
3128 }
3129
3130 /* The type is a string that may contain special characters of various
3131 kinds. Allow everything except space or { to appear; the actual content
3132 is checked by search_findtype_partial. */
3133
3134 while (*s != 0 && *s != '{' && !isspace(*s))
3135 {
3136 if (nameptr < sizeof(name) - 1) name[nameptr++] = *s;
3137 s++;
3138 }
3139 name[nameptr] = 0;
3140 while (isspace(*s)) s++;
3141
3142 /* Now check for the individual search type and any partial or default
3143 options. Only those types that are actually in the binary are valid. */
3144
3145 stype = search_findtype_partial(name, &partial, &affix, &affixlen,
3146 &starflags);
3147 if (stype < 0)
3148 {
3149 expand_string_message = search_error_message;
3150 goto EXPAND_FAILED;
3151 }
3152
3153 /* Check that a key was provided for those lookup types that need it,
3154 and was not supplied for those that use the query style. */
3155
13b685f9 3156 if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery))
059ec3d9
PH
3157 {
3158 if (key == NULL)
3159 {
3160 expand_string_message = string_sprintf("missing {key} for single-"
3161 "key \"%s\" lookup", name);
3162 goto EXPAND_FAILED;
3163 }
3164 }
3165 else
3166 {
3167 if (key != NULL)
3168 {
3169 expand_string_message = string_sprintf("a single key was given for "
3170 "lookup type \"%s\", which is not a single-key lookup type", name);
3171 goto EXPAND_FAILED;
3172 }
3173 }
3174
3175 /* Get the next string in brackets and expand it. It is the file name for
13b685f9
PH
3176 single-key+file lookups, and the whole query otherwise. In the case of
3177 queries that also require a file name (e.g. sqlite), the file name comes
3178 first. */
059ec3d9
PH
3179
3180 if (*s != '{') goto EXPAND_FAILED_CURLY;
3181 filename = expand_string_internal(s+1, TRUE, &s, skipping);
3182 if (filename == NULL) goto EXPAND_FAILED;
3183 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3184 while (isspace(*s)) s++;
3185
3186 /* If this isn't a single-key+file lookup, re-arrange the variables
13b685f9
PH
3187 to be appropriate for the search_ functions. For query-style lookups,
3188 there is just a "key", and no file name. For the special query-style +
3189 file types, the query (i.e. "key") starts with a file name. */
059ec3d9
PH
3190
3191 if (key == NULL)
3192 {
13b685f9 3193 while (isspace(*filename)) filename++;
059ec3d9 3194 key = filename;
13b685f9
PH
3195
3196 if (mac_islookup(stype, lookup_querystyle))
3197 {
3198 filename = NULL;
3199 }
3200 else
3201 {
3202 if (*filename != '/')
3203 {
3204 expand_string_message = string_sprintf(
3205 "absolute file name expected for \"%s\" lookup", name);
3206 goto EXPAND_FAILED;
3207 }
3208 while (*key != 0 && !isspace(*key)) key++;
3209 if (*key != 0) *key++ = 0;
3210 }
059ec3d9
PH
3211 }
3212
3213 /* If skipping, don't do the next bit - just lookup_value == NULL, as if
3214 the entry was not found. Note that there is no search_close() function.
3215 Files are left open in case of re-use. At suitable places in higher logic,
3216 search_tidyup() is called to tidy all open files. This can save opening
3217 the same file several times. However, files may also get closed when
3218 others are opened, if too many are open at once. The rule is that a
3219 handle should not be used after a second search_open().
3220
3221 Request that a partial search sets up $1 and maybe $2 by passing
3222 expand_setup containing zero. If its value changes, reset expand_nmax,
3223 since new variables will have been set. Note that at the end of this
3224 "lookup" section, the old numeric variables are restored. */
3225
3226 if (skipping)
3227 lookup_value = NULL;
3228 else
3229 {
3230 void *handle = search_open(filename, stype, 0, NULL, NULL);
3231 if (handle == NULL)
3232 {
3233 expand_string_message = search_error_message;
3234 goto EXPAND_FAILED;
3235 }
3236 lookup_value = search_find(handle, filename, key, partial, affix,
3237 affixlen, starflags, &expand_setup);
3238 if (search_find_defer)
3239 {
3240 expand_string_message =
3241 string_sprintf("lookup of \"%s\" gave DEFER: %s", key,
3242 search_error_message);
3243 goto EXPAND_FAILED;
3244 }
3245 if (expand_setup > 0) expand_nmax = expand_setup;
3246 }
3247
3248 /* The handling of "yes" and "no" result strings is now in a separate
3249 function that is also used by ${if} and ${extract}. */
3250
3251 switch(process_yesno(
3252 skipping, /* were previously skipping */
3253 lookup_value != NULL, /* success/failure indicator */
3254 save_lookup_value, /* value to reset for string2 */
3255 &s, /* input pointer */
3256 &yield, /* output pointer */
3257 &size, /* output size */
3258 &ptr, /* output current point */
3259 US"lookup")) /* condition type */
3260 {
3261 case 1: goto EXPAND_FAILED; /* when all is well, the */
3262 case 2: goto EXPAND_FAILED_CURLY; /* returned value is 0 */
3263 }
3264
3265 /* Restore external setting of expansion variables for carrying on
3266 at this level, and continue. */
3267
3268 restore_expand_strings(save_expand_nmax, save_expand_nstring,
3269 save_expand_nlength);
3270 continue;
3271 }
3272
3273 /* If Perl support is configured, handle calling embedded perl subroutines,
3274 unless locked out at this time. Syntax is ${perl{sub}} or ${perl{sub}{arg}}
3275 or ${perl{sub}{arg1}{arg2}} or up to a maximum of EXIM_PERL_MAX_ARGS
3276 arguments (defined below). */
3277
059ec3d9
PH
3278 #define EXIM_PERL_MAX_ARGS 8
3279
3280 case EITEM_PERL:
1a46a8c5
PH
3281 #ifndef EXIM_PERL
3282 expand_string_message = US"\"${perl\" encountered, but this facility "
3283 "is not included in this binary";
3284 goto EXPAND_FAILED;
3285
3286 #else /* EXIM_PERL */
059ec3d9
PH
3287 {
3288 uschar *sub_arg[EXIM_PERL_MAX_ARGS + 2];
3289 uschar *new_yield;
3290
3291 if ((expand_forbid & RDO_PERL) != 0)
3292 {
3293 expand_string_message = US"Perl calls are not permitted";
3294 goto EXPAND_FAILED;
3295 }
3296
3297 switch(read_subs(sub_arg, EXIM_PERL_MAX_ARGS + 1, 1, &s, skipping, TRUE,
3298 US"perl"))
3299 {
3300 case 1: goto EXPAND_FAILED_CURLY;
3301 case 2:
3302 case 3: goto EXPAND_FAILED;
3303 }
3304
3305 /* If skipping, we don't actually do anything */
3306
3307 if (skipping) continue;
3308
3309 /* Start the interpreter if necessary */
3310
3311 if (!opt_perl_started)
3312 {
3313 uschar *initerror;
3314 if (opt_perl_startup == NULL)
3315 {
3316 expand_string_message = US"A setting of perl_startup is needed when "
3317 "using the Perl interpreter";
3318 goto EXPAND_FAILED;
3319 }
3320 DEBUG(D_any) debug_printf("Starting Perl interpreter\n");
3321 initerror = init_perl(opt_perl_startup);
3322 if (initerror != NULL)
3323 {
3324 expand_string_message =
3325 string_sprintf("error in perl_startup code: %s\n", initerror);
3326 goto EXPAND_FAILED;
3327 }
3328 opt_perl_started = TRUE;
3329 }
3330
3331 /* Call the function */
3332
3333 sub_arg[EXIM_PERL_MAX_ARGS + 1] = NULL;
3334 new_yield = call_perl_cat(yield, &size, &ptr, &expand_string_message,
3335 sub_arg[0], sub_arg + 1);
3336
3337 /* NULL yield indicates failure; if the message pointer has been set to
3338 NULL, the yield was undef, indicating a forced failure. Otherwise the
3339 message will indicate some kind of Perl error. */
3340
3341 if (new_yield == NULL)
3342 {
3343 if (expand_string_message == NULL)
3344 {
3345 expand_string_message =
3346 string_sprintf("Perl subroutine \"%s\" returned undef to force "
3347 "failure", sub_arg[0]);
3348 expand_string_forcedfail = TRUE;
3349 }
3350 goto EXPAND_FAILED;
3351 }
3352
3353 /* Yield succeeded. Ensure forcedfail is unset, just in case it got
3354 set during a callback from Perl. */
3355
3356 expand_string_forcedfail = FALSE;
3357 yield = new_yield;
3358 continue;
3359 }
3360 #endif /* EXIM_PERL */
3361
fffda43a
TK
3362 /* Transform email address to "prvs" scheme to use
3363 as BATV-signed return path */
3364
3365 case EITEM_PRVS:
3366 {
3367 uschar *sub_arg[3];
3368 uschar *p,*domain;
3369
3370 switch(read_subs(sub_arg, 3, 2, &s, skipping, TRUE, US"prvs"))
3371 {
3372 case 1: goto EXPAND_FAILED_CURLY;
3373 case 2:
3374 case 3: goto EXPAND_FAILED;
3375 }
3376
3377 /* If skipping, we don't actually do anything */
3378 if (skipping) continue;
3379
3380 /* sub_arg[0] is the address */
3381 domain = Ustrrchr(sub_arg[0],'@');
3382 if ( (domain == NULL) || (domain == sub_arg[0]) || (Ustrlen(domain) == 1) )
3383 {
cb9328de
PH
3384 expand_string_message = US"prvs first argument must be a qualified email address";
3385 goto EXPAND_FAILED;
3386 }
3387
3388 /* Calculate the hash. The second argument must be a single-digit
3389 key number, or unset. */
3390
3391 if (sub_arg[2] != NULL &&
3392 (!isdigit(sub_arg[2][0]) || sub_arg[2][1] != 0))
3393 {
3394 expand_string_message = US"prvs second argument must be a single digit";
fffda43a
TK
3395 goto EXPAND_FAILED;
3396 }
3397
fffda43a
TK
3398 p = prvs_hmac_sha1(sub_arg[0],sub_arg[1],sub_arg[2],prvs_daystamp(7));
3399 if (p == NULL)
3400 {
cb9328de 3401 expand_string_message = US"prvs hmac-sha1 conversion failed";
fffda43a
TK
3402 goto EXPAND_FAILED;
3403 }
3404
3405 /* Now separate the domain from the local part */
3406 *domain++ = '\0';
3407
3408 yield = string_cat(yield,&size,&ptr,US"prvs=",5);
3409 string_cat(yield,&size,&ptr,sub_arg[0],Ustrlen(sub_arg[0]));
3410 string_cat(yield,&size,&ptr,US"/",1);
3411 string_cat(yield,&size,&ptr,(sub_arg[2] != NULL) ? sub_arg[2] : US"0", 1);
3412 string_cat(yield,&size,&ptr,prvs_daystamp(7),3);
3413 string_cat(yield,&size,&ptr,p,6);
3414 string_cat(yield,&size,&ptr,US"@",1);
3415 string_cat(yield,&size,&ptr,domain,Ustrlen(domain));
3416
3417 continue;
3418 }
3419
3420 /* Check a prvs-encoded address for validity */
3421
3422 case EITEM_PRVSCHECK:
3423 {
3424 uschar *sub_arg[3];
3425 int mysize = 0, myptr = 0;
3426 const pcre *re;
3427 uschar *p;
72fdd6ae
PH
3428
3429 /* TF: Ugliness: We want to expand parameter 1 first, then set
fffda43a
TK
3430 up expansion variables that are used in the expansion of
3431 parameter 2. So we clone the string for the first
72fdd6ae
PH
3432 expansion, where we only expand parameter 1.
3433
3434 PH: Actually, that isn't necessary. The read_subs() function is
3435 designed to work this way for the ${if and ${lookup expansions. I've
3436 tidied the code.
3437 */
fffda43a
TK
3438
3439 /* Reset expansion variables */
3440 prvscheck_result = NULL;
3441 prvscheck_address = NULL;
3442 prvscheck_keynum = NULL;
3443
72fdd6ae 3444 switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, US"prvs"))
fffda43a
TK
3445 {
3446 case 1: goto EXPAND_FAILED_CURLY;
3447 case 2:
3448 case 3: goto EXPAND_FAILED;
3449 }
3450
3451 re = regex_must_compile(US"^prvs\\=(.+)\\/([0-9])([0-9]{3})([A-F0-9]{6})\\@(.+)$",
3452 TRUE,FALSE);
3453
72fdd6ae
PH
3454 if (regex_match_and_setup(re,sub_arg[0],0,-1))
3455 {
fffda43a
TK
3456 uschar *local_part = string_copyn(expand_nstring[1],expand_nlength[1]);
3457 uschar *key_num = string_copyn(expand_nstring[2],expand_nlength[2]);
3458 uschar *daystamp = string_copyn(expand_nstring[3],expand_nlength[3]);
3459 uschar *hash = string_copyn(expand_nstring[4],expand_nlength[4]);
3460 uschar *domain = string_copyn(expand_nstring[5],expand_nlength[5]);
3461
3462 DEBUG(D_expand) debug_printf("prvscheck localpart: %s\n", local_part);
3463 DEBUG(D_expand) debug_printf("prvscheck key number: %s\n", key_num);
3464 DEBUG(D_expand) debug_printf("prvscheck daystamp: %s\n", daystamp);
3465 DEBUG(D_expand) debug_printf("prvscheck hash: %s\n", hash);
3466 DEBUG(D_expand) debug_printf("prvscheck domain: %s\n", domain);
3467
3468 /* Set up expansion variables */
3469 prvscheck_address = string_cat(NULL, &mysize, &myptr, local_part, Ustrlen(local_part));
2740a2ca 3470 string_cat(prvscheck_address,&mysize,&myptr,US"@",1);
fffda43a
TK
3471 string_cat(prvscheck_address,&mysize,&myptr,domain,Ustrlen(domain));
3472 prvscheck_address[myptr] = '\0';
3473 prvscheck_keynum = string_copy(key_num);
3474
72fdd6ae
PH
3475 /* Now expand the second argument */
3476 switch(read_subs(sub_arg, 1, 1, &s, skipping, FALSE, US"prvs"))
fffda43a
TK
3477 {
3478 case 1: goto EXPAND_FAILED_CURLY;
3479 case 2:
3480 case 3: goto EXPAND_FAILED;
3481 }
3482
fffda43a 3483 /* Now we have the key and can check the address. */
72fdd6ae
PH
3484
3485 p = prvs_hmac_sha1(prvscheck_address, sub_arg[0], prvscheck_keynum,
3486 daystamp);
3487
fffda43a
TK
3488 if (p == NULL)
3489 {
3490 expand_string_message = US"hmac-sha1 conversion failed";
3491 goto EXPAND_FAILED;
3492 }
3493
3494 DEBUG(D_expand) debug_printf("prvscheck: received hash is %s\n", hash);
3495 DEBUG(D_expand) debug_printf("prvscheck: own hash is %s\n", p);
72fdd6ae 3496
fffda43a
TK
3497 if (Ustrcmp(p,hash) == 0)
3498 {
3499 /* Success, valid BATV address. Now check the expiry date. */
3500 uschar *now = prvs_daystamp(0);
3501 unsigned int inow = 0,iexpire = 1;
3502
ff790e47
PH
3503 (void)sscanf(CS now,"%u",&inow);
3504 (void)sscanf(CS daystamp,"%u",&iexpire);
fffda43a
TK
3505
3506 /* When "iexpire" is < 7, a "flip" has occured.
3507 Adjust "inow" accordingly. */
3508 if ( (iexpire < 7) && (inow >= 993) ) inow = 0;
3509
3510 if (iexpire > inow)
3511 {
3512 prvscheck_result = US"1";
3513 DEBUG(D_expand) debug_printf("prvscheck: success, $pvrs_result set to 1\n");
3514 }
3515 else
3516 {
3517 prvscheck_result = NULL;
3518 DEBUG(D_expand) debug_printf("prvscheck: signature expired, $pvrs_result unset\n");
3519 }
3520 }
3521 else
3522 {
3523 prvscheck_result = NULL;
3524 DEBUG(D_expand) debug_printf("prvscheck: hash failure, $pvrs_result unset\n");
3525 }
72fdd6ae
PH
3526
3527 /* Now expand the final argument. We leave this till now so that
3528 it can include $prvscheck_result. */
3529
3530 switch(read_subs(sub_arg, 1, 0, &s, skipping, TRUE, US"prvs"))
3531 {
3532 case 1: goto EXPAND_FAILED_CURLY;
3533 case 2:
3534 case 3: goto EXPAND_FAILED;
3535 }
3536
3537 if (sub_arg[0] == NULL || *sub_arg[0] == '\0')
3538 yield = string_cat(yield,&size,&ptr,prvscheck_address,Ustrlen(prvscheck_address));
3539 else
3540 yield = string_cat(yield,&size,&ptr,sub_arg[0],Ustrlen(sub_arg[0]));
3541
3542 /* Reset the "internal" variables afterwards, because they are in
3543 dynamic store that will be reclaimed if the expansion succeeded. */
3544
3545 prvscheck_address = NULL;
3546 prvscheck_keynum = NULL;
3547 }
fffda43a
TK
3548 else
3549 {
3550 /* Does not look like a prvs encoded address, return the empty string.
72fdd6ae
PH
3551 We need to make sure all subs are expanded first, so as to skip over
3552 the entire item. */
3553
5a03bd24 3554 switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, US"prvs"))
fffda43a
TK
3555 {
3556 case 1: goto EXPAND_FAILED_CURLY;
3557 case 2:
3558 case 3: goto EXPAND_FAILED;
3559 }
3560 }
3561
3562 continue;
3563 }
3564
059ec3d9
PH
3565 /* Handle "readfile" to insert an entire file */
3566
3567 case EITEM_READFILE:
3568 {
3569 FILE *f;
3570 uschar *sub_arg[2];
3571
3572 if ((expand_forbid & RDO_READFILE) != 0)
3573 {
3574 expand_string_message = US"file insertions are not permitted";
3575 goto EXPAND_FAILED;
3576 }
3577
3578 switch(read_subs(sub_arg, 2, 1, &s, skipping, TRUE, US"readfile"))
3579 {
3580 case 1: goto EXPAND_FAILED_CURLY;
3581 case 2:
3582 case 3: goto EXPAND_FAILED;
3583 }
3584
3585 /* If skipping, we don't actually do anything */
3586
3587 if (skipping) continue;
3588
3589 /* Open the file and read it */
3590
3591 f = Ufopen(sub_arg[0], "rb");
3592 if (f == NULL)
3593 {
3594 expand_string_message = string_open_failed(errno, "%s", sub_arg[0]);
3595 goto EXPAND_FAILED;
3596 }
3597
3598 yield = cat_file(f, yield, &size, &ptr, sub_arg[1]);
f1e894f3 3599 (void)fclose(f);
059ec3d9
PH
3600 continue;
3601 }
3602
3603 /* Handle "readsocket" to insert data from a Unix domain socket */
3604
3605 case EITEM_READSOCK:
3606 {
3607 int fd;
3608 int timeout = 5;
3609 int save_ptr = ptr;
3610 FILE *f;
3611 struct sockaddr_un sockun; /* don't call this "sun" ! */
3612 uschar *arg;
3613 uschar *sub_arg[4];
3614
3615 if ((expand_forbid & RDO_READSOCK) != 0)
3616 {
3617 expand_string_message = US"socket insertions are not permitted";
3618 goto EXPAND_FAILED;
3619 }
3620
3621 /* Read up to 4 arguments, but don't do the end of item check afterwards,
3622 because there may be a string for expansion on failure. */
3623
3624 switch(read_subs(sub_arg, 4, 2, &s, skipping, FALSE, US"readsocket"))
3625 {
3626 case 1: goto EXPAND_FAILED_CURLY;
3627 case 2: /* Won't occur: no end check */
3628 case 3: goto EXPAND_FAILED;
3629 }
3630
3631 /* Sort out timeout, if given */
3632
3633 if (sub_arg[2] != NULL)
3634 {
3635 timeout = readconf_readtime(sub_arg[2], 0, FALSE);
3636 if (timeout < 0)
3637 {
3638 expand_string_message = string_sprintf("bad time value %s",
3639 sub_arg[2]);
3640 goto EXPAND_FAILED;
3641 }
3642 }
3643 else sub_arg[3] = NULL; /* No eol if no timeout */
3644
1cce3af8
PH
3645 /* If skipping, we don't actually do anything. Otherwise, arrange to
3646 connect to either an IP or a Unix socket. */
059ec3d9
PH
3647
3648 if (!skipping)
3649 {
1cce3af8 3650 /* Handle an IP (internet) domain */
059ec3d9 3651
91ecef39 3652 if (Ustrncmp(sub_arg[0], "inet:", 5) == 0)
059ec3d9 3653 {
1cce3af8
PH
3654 BOOL connected = FALSE;
3655 int namelen, port;
3656 host_item shost;
3657 host_item *h;
3658 uschar *server_name = sub_arg[0] + 5;
3659 uschar *port_name = Ustrrchr(server_name, ':');
3660
3661 /* Sort out the port */
3662
3663 if (port_name == NULL)
3664 {
3665 expand_string_message =
3666 string_sprintf("missing port for readsocket %s", sub_arg[0]);
3667 goto EXPAND_FAILED;
3668 }
3669 *port_name++ = 0; /* Terminate server name */
3670
3671 if (isdigit(*port_name))
3672 {
3673 uschar *end;
3674 port = Ustrtol(port_name, &end, 0);
3675 if (end != port_name + Ustrlen(port_name))
3676 {
3677 expand_string_message =
3678 string_sprintf("invalid port number %s", port_name);
3679 goto EXPAND_FAILED;
3680 }
3681 }
3682 else
3683 {
3684 struct servent *service_info = getservbyname(CS port_name, "tcp");
3685 if (service_info == NULL)
3686 {
3687 expand_string_message = string_sprintf("unknown port \"%s\"",
3688 port_name);
3689 goto EXPAND_FAILED;
3690 }
3691 port = ntohs(service_info->s_port);
3692 }
3693
3694 /* Sort out the server. */
3695
3696 shost.next = NULL;
3697 shost.address = NULL;
3698 shost.port = port;
3699 shost.mx = -1;
3700
3701 namelen = Ustrlen(server_name);
3702
3703 /* Anything enclosed in [] must be an IP address. */
3704
3705 if (server_name[0] == '[' &&
3706 server_name[namelen - 1] == ']')
3707 {
3708 server_name[namelen - 1] = 0;
3709 server_name++;
3710 if (string_is_ip_address(server_name, NULL) == 0)
3711 {
3712 expand_string_message =
3713 string_sprintf("malformed IP address \"%s\"", server_name);
3714 goto EXPAND_FAILED;
3715 }
3716 shost.name = shost.address = server_name;
3717 }
3718
3719 /* Otherwise check for an unadorned IP address */
3720
3721 else if (string_is_ip_address(server_name, NULL) != 0)
3722 shost.name = shost.address = server_name;
3723
3724 /* Otherwise lookup IP address(es) from the name */
3725
3726 else
3727 {
3728 shost.name = server_name;
3729 if (host_find_byname(&shost, NULL, NULL, FALSE) != HOST_FOUND)
3730 {
3731 expand_string_message =
3732 string_sprintf("no IP address found for host %s", shost.name);
3733 goto EXPAND_FAILED;
3734 }
3735 }
3736
3737 /* Try to connect to the server - test each IP till one works */
3738
3739 for (h = &shost; h != NULL; h = h->next)
3740 {
3741 int af = (Ustrchr(h->address, ':') != 0)? AF_INET6 : AF_INET;
3742 if ((fd = ip_socket(SOCK_STREAM, af)) == -1)
3743 {
3744 expand_string_message = string_sprintf("failed to create socket: "
3745 "%s", strerror(errno));
3746 goto SOCK_FAIL;
3747 }
3748
3749 if (ip_connect(fd, af, h->address, port, timeout) == 0)
3750 {
3751 connected = TRUE;
3752 break;
3753 }
3754 }
3755
3756 if (!connected)
3757 {
3758 expand_string_message = string_sprintf("failed to connect to "
3759 "socket %s: couldn't connect to any host", sub_arg[0],
3760 strerror(errno));
3761 goto SOCK_FAIL;
3762 }
059ec3d9
PH
3763 }
3764
1cce3af8
PH
3765 /* Handle a Unix domain socket */
3766
3767 else
059ec3d9 3768 {
1cce3af8
PH
3769 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
3770 {
3771 expand_string_message = string_sprintf("failed to create socket: %s",
3772 strerror(errno));
3773 goto SOCK_FAIL;
3774 }
3775
3776 sockun.sun_family = AF_UNIX;
3777 sprintf(sockun.sun_path, "%.*s", (int)(sizeof(sockun.sun_path)-1),
3778 sub_arg[0]);
3779 if(connect(fd, (struct sockaddr *)(&sockun), sizeof(sockun)) == -1)
3780 {
3781 expand_string_message = string_sprintf("failed to connect to socket "
3782 "%s: %s", sub_arg[0], strerror(errno));
3783 goto SOCK_FAIL;
3784 }
059ec3d9 3785 }
1cce3af8 3786
059ec3d9
PH
3787 DEBUG(D_expand) debug_printf("connected to socket %s\n", sub_arg[0]);
3788
3789 /* Write the request string, if not empty */
3790
3791 if (sub_arg[1][0] != 0)
3792 {
3793 int len = Ustrlen(sub_arg[1]);
3794 DEBUG(D_expand) debug_printf("writing \"%s\" to socket\n",
3795 sub_arg[1]);
3796 if (write(fd, sub_arg[1], len) != len)
3797 {
3798 expand_string_message = string_sprintf("request write to socket "
3799 "failed: %s", strerror(errno));
3800 goto SOCK_FAIL;
3801 }
3802 }
3803
3804 /* Now we need to read from the socket, under a timeout. The function
3805 that reads a file can be used. */
3806
3807 f = fdopen(fd, "rb");
3808 sigalrm_seen = FALSE;
3809 alarm(timeout);
3810 yield = cat_file(f, yield, &size, &ptr, sub_arg[3]);
3811 alarm(0);
f1e894f3 3812 (void)fclose(f);
059ec3d9
PH
3813
3814 /* After a timeout, we restore the pointer in the result, that is,
3815 make sure we add nothing from the socket. */
3816
3817 if (sigalrm_seen)
3818 {
3819 ptr = save_ptr;
1cce3af8 3820 expand_string_message = US "socket read timed out";
059ec3d9
PH
3821 goto SOCK_FAIL;
3822 }
3823 }
3824
3825 /* The whole thing has worked (or we were skipping). If there is a
3826 failure string following, we need to skip it. */
3827
3828 if (*s == '{')
3829 {
3830 if (expand_string_internal(s+1, TRUE, &s, TRUE) == NULL)
3831 goto EXPAND_FAILED;
3832 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3833 while (isspace(*s)) s++;
3834 }
3835 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3836 continue;
3837
3838 /* Come here on failure to create socket, connect socket, write to the
3839 socket, or timeout on reading. If another substring follows, expand and
3840 use it. Otherwise, those conditions give expand errors. */
3841
3842 SOCK_FAIL:
3843 if (*s != '{') goto EXPAND_FAILED;
3844 DEBUG(D_any) debug_printf("%s\n", expand_string_message);
3845 arg = expand_string_internal(s+1, TRUE, &s, FALSE);
3846 if (arg == NULL) goto EXPAND_FAILED;
3847 yield = string_cat(yield, &size, &ptr, arg, Ustrlen(arg));
3848 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3849 while (isspace(*s)) s++;
3850 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3851 continue;
3852 }
3853
3854 /* Handle "run" to execute a program. */
3855
3856 case EITEM_RUN:
3857 {
3858 FILE *f;
059ec3d9
PH
3859 uschar *arg;
3860 uschar **argv;
3861 pid_t pid;
3862 int fd_in, fd_out;
3863 int lsize = 0;
3864 int lptr = 0;
3865
3866 if ((expand_forbid & RDO_RUN) != 0)
3867 {
3868 expand_string_message = US"running a command is not permitted";
3869 goto EXPAND_FAILED;
3870 }
3871
3872 while (isspace(*s)) s++;
3873 if (*s != '{') goto EXPAND_FAILED_CURLY;
3874 arg = expand_string_internal(s+1, TRUE, &s, skipping);
3875 if (arg == NULL) goto EXPAND_FAILED;
3876 while (isspace(*s)) s++;
3877 if (*s++ != '}') goto EXPAND_FAILED_CURLY;
3878
3879 if (skipping) /* Just pretend it worked when we're skipping */
3880 {
3881 runrc = 0;
3882 }
3883 else
3884 {
3885 if (!transport_set_up_command(&argv, /* anchor for arg list */
3886 arg, /* raw command */
3887 FALSE, /* don't expand the arguments */
3888 0, /* not relevant when... */
3889 NULL, /* no transporting address */
3890 US"${run} expansion", /* for error messages */
3891 &expand_string_message)) /* where to put error message */
3892 {
3893 goto EXPAND_FAILED;
3894 }
3895
3896 /* Create the child process, making it a group leader. */
3897
3898 pid = child_open(argv, NULL, 0077, &fd_in, &fd_out, TRUE);
3899
3900 if (pid < 0)
3901 {
3902 expand_string_message =
3903 string_sprintf("couldn't create child process: %s", strerror(errno));
3904 goto EXPAND_FAILED;
3905 }
3906
3907 /* Nothing is written to the standard input. */
3908
f1e894f3 3909 (void)close(fd_in);
059ec3d9
PH
3910
3911 /* Wait for the process to finish, applying the timeout, and inspect its
3912 return code for serious disasters. Simple non-zero returns are passed on.
3913 */
3914
3915 if ((runrc = child_close(pid, 60)) < 0)
3916 {
3917 if (runrc == -256)
3918 {
3919 expand_string_message = string_sprintf("command timed out");
3920 killpg(pid, SIGKILL); /* Kill the whole process group */
3921 }
3922
3923 else if (runrc == -257)
3924 expand_string_message = string_sprintf("wait() failed: %s",
3925 strerror(errno));
3926
3927 else
3928 expand_string_message = string_sprintf("command killed by signal %d",
3929 -runrc);
3930
3931 goto EXPAND_FAILED;
3932 }
3933
3934 /* Read the pipe to get the command's output into $value (which is kept
3935 in lookup_value). */
3936
3937 f = fdopen(fd_out, "rb");
059ec3d9
PH
3938 lookup_value = NULL;
3939 lookup_value = cat_file(f, lookup_value, &lsize, &lptr, NULL);
f1e894f3 3940 (void)fclose(f);
059ec3d9
PH
3941 }
3942
d20976dc 3943 /* Process the yes/no strings; $value may be useful in both cases */
059ec3d9
PH
3944
3945 switch(process_yesno(
3946 skipping, /* were previously skipping */
3947 runrc == 0, /* success/failure indicator */
d20976dc 3948 lookup_value, /* value to reset for string2 */
059ec3d9
PH
3949 &s, /* input pointer */
3950 &yield, /* output pointer */
3951 &size, /* output size */
3952 &ptr, /* output current point */
3953 US"run")) /* condition type */
3954 {
3955 case 1: goto EXPAND_FAILED; /* when all is well, the */
3956 case 2: goto EXPAND_FAILED_CURLY; /* returned value is 0 */
3957 }
3958
3959 continue;
3960 }
3961
3962 /* Handle character translation for "tr" */
3963
3964 case EITEM_TR:
3965 {
3966 int oldptr = ptr;
3967 int o2m;
3968 uschar *sub[3];
3969
3970 switch(read_subs(sub, 3, 3, &s, skipping, TRUE, US"tr"))
3971 {
3972 case 1: goto EXPAND_FAILED_CURLY;
3973 case 2:
3974 case 3: goto EXPAND_FAILED;
3975 }
3976
3977 yield = string_cat(yield, &size, &ptr, sub[0], Ustrlen(sub[0]));
3978 o2m = Ustrlen(sub[2]) - 1;
3979
3980 if (o2m >= 0) for (; oldptr < ptr; oldptr++)
3981 {
3982 uschar *m = Ustrrchr(sub[1], yield[oldptr]);
3983 if (m != NULL)
3984 {
3985 int o = m - sub[1];
3986 yield[oldptr] = sub[2][(o < o2m)? o : o2m];
3987 }
3988 }
3989
3990 continue;
3991 }
3992
3993 /* Handle "hash", "length", "nhash", and "substr" when they are given with
3994 expanded arguments. */
3995
3996 case EITEM_HASH:
3997 case EITEM_LENGTH:
3998 case EITEM_NHASH:
3999 case EITEM_SUBSTR:
4000 {
4001 int i;
4002 int len;
4003 uschar *ret;
4004 int val[2] = { 0, -1 };
4005 uschar *sub[3];
4006
4007 /* "length" takes only 2 arguments whereas the others take 2 or 3.
4008 Ensure that sub[2] is set in the ${length case. */
4009
4010 sub[2] = NULL;
4011 switch(read_subs(sub, (item_type == EITEM_LENGTH)? 2:3, 2, &s, skipping,
4012 TRUE, name))
4013 {
4014 case 1: goto EXPAND_FAILED_CURLY;
4015 case 2:
4016 case 3: goto EXPAND_FAILED;
4017 }
4018
4019 /* Juggle the arguments if there are only two of them: always move the
4020 string to the last position and make ${length{n}{str}} equivalent to
4021 ${substr{0}{n}{str}}. See the defaults for val[] above. */
4022
4023 if (sub[2] == NULL)
4024 {
4025 sub[2] = sub[1];
4026 sub[1] = NULL;
4027 if (item_type == EITEM_LENGTH)
4028 {
4029 sub[1] = sub[0];
4030 sub[0] = NULL;
4031 }
4032 }
4033
4034 for (i = 0; i < 2; i++)
4035 {
4036 if (sub[i] == NULL) continue;
4037 val[i] = (int)Ustrtol(sub[i], &ret, 10);
4038 if (*ret != 0 || (i != 0 && val[i] < 0))
4039 {
4040 expand_string_message = string_sprintf("\"%s\" is not a%s number "
4041 "(in \"%s\" expansion)", sub[i], (i != 0)? " positive" : "", name);
4042 goto EXPAND_FAILED;
4043 }
4044 }
4045
4046 ret =
4047 (item_type == EITEM_HASH)?
4048 compute_hash(sub[2], val[0], val[1], &len) :
4049 (item_type == EITEM_NHASH)?
4050 compute_nhash(sub[2], val[0], val[1], &len) :
4051 extract_substr(sub[2], val[0], val[1], &len);
4052
4053 if (ret == NULL) goto EXPAND_FAILED;
4054 y