testcases for value return
[exim.git] / src / src / spool_in.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
f9ba5e22 5/* Copyright (c) University of Cambridge 1995 - 2018 */
1e1ddfac 6/* Copyright (c) The Exim Maintainers 2020 */
059ec3d9
PH
7/* See the file NOTICE for conditions of use and distribution. */
8
9/* Functions for reading spool files. When compiling for a utility (eximon),
10not all are needed, and some functionality can be cut out. */
11
12
13#include "exim.h"
14
15
16
17#ifndef COMPILE_UTILITY
18/*************************************************
19* Open and lock data file *
20*************************************************/
21
22/* The data file is the one that is used for locking, because the header file
23can get replaced during delivery because of header rewriting. The file has
24to opened with write access so that we can get an exclusive lock, but in
25fact it won't be written to. Just in case there's a major disaster (e.g.
26overwriting some other file descriptor with the value of this one), open it
27with append.
28
92b0827a
JH
29As called by deliver_message() (at least) we are operating as root.
30
059ec3d9 31Argument: the id of the message
789f8a4f 32Returns: fd if file successfully opened and locked, else -1
059ec3d9 33
789f8a4f 34Side effect: message_subdir is set for the (possibly split) spool directory
059ec3d9
PH
35*/
36
789f8a4f 37int
059ec3d9
PH
38spool_open_datafile(uschar *id)
39{
059ec3d9
PH
40struct stat statbuf;
41flock_t lock_data;
789f8a4f 42int fd;
059ec3d9
PH
43
44/* If split_spool_directory is set, first look for the file in the appropriate
45sub-directory of the input directory. If it is not found there, try the input
46directory itself, to pick up leftovers from before the splitting. If split_
47spool_directory is not set, first look in the main input directory. If it is
48not found there, try the split sub-directory, in case it is left over from a
49splitting state. */
50
d7978c0f 51for (int i = 0; i < 2; i++)
059ec3d9 52 {
41313d92 53 uschar * fname;
059ec3d9 54 int save_errno;
9befa1ca 55
59a93276 56 set_subdir_str(message_subdir, id, i);
41313d92
JH
57 fname = spool_fname(US"input", message_subdir, id, US"-D");
58 DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname);
a2da3176 59
85defcf0
PP
60 /* We protect against symlink attacks both in not propagating the
61 * file-descriptor to other processes as we exec, and also ensuring that we
62 * don't even open symlinks.
63 * No -D file inside the spool area should be a symlink.
64 */
92b0827a
JH
65 if ((fd = Uopen(fname,
66#ifdef O_CLOEXEC
67 O_CLOEXEC |
85defcf0
PP
68#endif
69#ifdef O_NOFOLLOW
70 O_NOFOLLOW |
92b0827a
JH
71#endif
72 O_RDWR | O_APPEND, 0)) >= 0)
789f8a4f 73 break;
059ec3d9
PH
74 save_errno = errno;
75 if (errno == ENOENT)
76 {
77 if (i == 0) continue;
8768d548 78 if (!f.queue_running)
9befa1ca 79 log_write(0, LOG_MAIN, "Spool%s%s file %s-D not found",
12cf7615
JH
80 *queue_name ? US" Q=" : US"",
81 *queue_name ? queue_name : US"",
9befa1ca 82 id);
059ec3d9 83 }
9befa1ca
JH
84 else
85 log_write(0, LOG_MAIN, "Spool error for %s: %s", fname, strerror(errno));
059ec3d9 86 errno = save_errno;
789f8a4f 87 return -1;
059ec3d9
PH
88 }
89
90/* File is open and message_subdir is set. Set the close-on-exec flag, and lock
91the file. We lock only the first line of the file (containing the message ID)
92because this apparently is needed for running Exim under Cygwin. If the entire
93file is locked in one process, a sub-process cannot access it, even when passed
94an open file descriptor (at least, I think that's the Cygwin story). On real
95Unix systems it doesn't make any difference as long as Exim is consistent in
96what it locks. */
97
92b0827a
JH
98#ifndef O_CLOEXEC
99(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
100#endif
059ec3d9
PH
101
102lock_data.l_type = F_WRLCK;
103lock_data.l_whence = SEEK_SET;
104lock_data.l_start = 0;
105lock_data.l_len = SPOOL_DATA_START_OFFSET;
106
789f8a4f 107if (fcntl(fd, F_SETLK, &lock_data) < 0)
059ec3d9 108 {
ff966302
JH
109 log_write(L_skip_delivery, LOG_MAIN,
110 "Spool file for %s is locked (another process is handling this message)",
111 id);
789f8a4f 112 (void)close(fd);
059ec3d9 113 errno = 0;
789f8a4f 114 return -1;
059ec3d9
PH
115 }
116
117/* Get the size of the data; don't include the leading filename line
118in the count, but add one for the newline before the data. */
119
789f8a4f 120if (fstat(fd, &statbuf) == 0)
059ec3d9
PH
121 {
122 message_body_size = statbuf.st_size - SPOOL_DATA_START_OFFSET;
123 message_size = message_body_size + 1;
124 }
125
789f8a4f 126return fd;
059ec3d9
PH
127}
128#endif /* COMPILE_UTILITY */
129
130
131
132/*************************************************
133* Read non-recipients tree from spool file *
134*************************************************/
135
136/* The tree of non-recipients is written to the spool file in a form that
137makes it easy to read back into a tree. The format is as follows:
138
139 . Each node is preceded by two letter(Y/N) indicating whether it has left
140 or right children. There's one space after the two flags, before the name.
141
142 . The left subtree (if any) then follows, then the right subtree (if any).
143
144This function is entered with the next input line in the buffer. Note we must
145save the right flag before recursing with the same buffer.
146
147Once the tree is read, we re-construct the balance fields by scanning the tree.
148I forgot to write them out originally, and the compatible fix is to do it this
149way. This initial local recursing function does the necessary.
150
151Arguments:
152 node tree node
153
154Returns: maximum depth below the node, including the node itself
155*/
156
157static int
158count_below(tree_node *node)
159{
160int nleft, nright;
161if (node == NULL) return 0;
162nleft = count_below(node->left);
163nright = count_below(node->right);
164node->balance = (nleft > nright)? 1 : ((nright > nleft)? 2 : 0);
165return 1 + ((nleft > nright)? nleft : nright);
166}
167
168/* This is the real function...
169
170Arguments:
171 connect pointer to the root of the tree
172 f FILE to read data from
173 buffer contains next input line; further lines read into it
174 buffer_size size of the buffer
175
176Returns: FALSE on format error
177*/
178
179static BOOL
180read_nonrecipients_tree(tree_node **connect, FILE *f, uschar *buffer,
181 int buffer_size)
182{
183tree_node *node;
184int n = Ustrlen(buffer);
185BOOL right = buffer[1] == 'Y';
186
187if (n < 5) return FALSE; /* malformed line */
188buffer[n-1] = 0; /* Remove \n */
d81d33cf 189node = store_get(sizeof(tree_node) + n - 3, TRUE); /* rcpt names tainted */
059ec3d9
PH
190*connect = node;
191Ustrcpy(node->name, buffer + 3);
192node->data.ptr = NULL;
193
194if (buffer[0] == 'Y')
195 {
196 if (Ufgets(buffer, buffer_size, f) == NULL ||
197 !read_nonrecipients_tree(&node->left, f, buffer, buffer_size))
198 return FALSE;
199 }
200else node->left = NULL;
201
202if (right)
203 {
204 if (Ufgets(buffer, buffer_size, f) == NULL ||
205 !read_nonrecipients_tree(&node->right, f, buffer, buffer_size))
206 return FALSE;
207 }
208else node->right = NULL;
209
210(void) count_below(*connect);
211return TRUE;
212}
213
214
215
216
059ec3d9
PH
217/* Reset all the global variables to their default values. However, there is
218one exception. DO NOT change the default value of dont_deliver, because it may
219be forced by an external setting. */
220
4b4856ff
JH
221void
222spool_clear_header_globals(void)
223{
38a0a95f 224acl_var_c = acl_var_m = NULL;
059ec3d9
PH
225authenticated_id = NULL;
226authenticated_sender = NULL;
8768d548
JH
227f.allow_unqualified_recipient = FALSE;
228f.allow_unqualified_sender = FALSE;
059ec3d9
PH
229body_linecount = 0;
230body_zerocount = 0;
8768d548
JH
231f.deliver_firsttime = FALSE;
232f.deliver_freeze = FALSE;
059ec3d9 233deliver_frozen_at = 0;
8768d548
JH
234f.deliver_manual_thaw = FALSE;
235/* f.dont_deliver must NOT be reset */
059ec3d9 236header_list = header_last = NULL;
b08b24c8 237host_lookup_deferred = FALSE;
059ec3d9
PH
238host_lookup_failed = FALSE;
239interface_address = NULL;
240interface_port = 0;
8768d548 241f.local_error_message = FALSE;
9723f966 242#ifdef HAVE_LOCAL_SCAN
059ec3d9 243local_scan_data = NULL;
9723f966 244#endif
d677b2f2 245max_received_linelength = 0;
059ec3d9
PH
246message_linecount = 0;
247received_protocol = NULL;
248received_count = 0;
249recipients_list = NULL;
250sender_address = NULL;
251sender_fullhost = NULL;
252sender_helo_name = NULL;
253sender_host_address = NULL;
254sender_host_name = NULL;
255sender_host_port = 0;
256sender_host_authenticated = NULL;
257sender_ident = NULL;
8768d548
JH
258f.sender_local = FALSE;
259f.sender_set_untrusted = FALSE;
1f5b4c3d 260smtp_active_hostname = primary_hostname;
328c5688 261#ifndef COMPILE_UTILITY
8768d548 262f.spool_file_wireformat = FALSE;
328c5688 263#endif
059ec3d9
PH
264tree_nonrecipients = NULL;
265
8523533c
TK
266#ifdef EXPERIMENTAL_BRIGHTMAIL
267bmi_run = 0;
268bmi_verdicts = NULL;
269#endif
270
80a47a2c 271#ifndef DISABLE_DKIM
9e5d6b55 272dkim_signers = NULL;
8768d548 273f.dkim_disable_verify = FALSE;
64b67b65 274dkim_collect_input = 0;
f7572e5a
TK
275#endif
276
01603eec 277#ifndef DISABLE_TLS
817d9f57 278tls_in.certificate_verified = FALSE;
c0635b6d 279# ifdef SUPPORT_DANE
53a7196b
JH
280tls_in.dane_verified = FALSE;
281# endif
da40b1ec 282tls_in.ver = tls_in.cipher = NULL;
790fbb71
JH
283# ifndef COMPILE_UTILITY /* tls support fns not built in */
284tls_free_cert(&tls_in.ourcert);
285tls_free_cert(&tls_in.peercert);
286# endif
817d9f57
JH
287tls_in.peerdn = NULL;
288tls_in.sni = NULL;
44662487 289tls_in.ocsp = OCSP_NOT_REQ;
7be682ca 290#endif
059ec3d9 291
8523533c 292#ifdef WITH_CONTENT_SCAN
3481c572
JH
293spam_bar = NULL;
294spam_score = NULL;
8523533c
TK
295spam_score_int = NULL;
296#endif
297
8c5d388a 298#if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
7ade712c 299message_smtputf8 = FALSE;
3c8b3577 300message_utf8_downconvert = 0;
7ade712c
JH
301#endif
302
6c1c3d1d
WB
303dsn_ret = 0;
304dsn_envid = NULL;
4b4856ff
JH
305}
306
307
308/*************************************************
309* Read spool header file *
310*************************************************/
311
312/* This function reads a spool header file and places the data into the
313appropriate global variables. The header portion is always read, but header
314structures are built only if read_headers is set true. It isn't, for example,
315while generating -bp output.
316
317It may be possible for blocks of nulls (binary zeroes) to get written on the
318end of a file if there is a system crash during writing. It was observed on an
319earlier version of Exim that omitted to fsync() the files - this is thought to
320have been the cause of that incident, but in any case, this code must be robust
321against such an event, and if such a file is encountered, it must be treated as
322malformed.
323
324As called from deliver_message() (at least) we are running as root.
325
326Arguments:
327 name name of the header file, including the -H
328 read_headers TRUE if in-store header structures are to be built
329 subdir_set TRUE is message_subdir is already set
330
331Returns: spool_read_OK success
332 spool_read_notopen open failed
333 spool_read_enverror error in the envelope portion
334 spool_read_hdrerror error in the header portion
335*/
336
337int
338spool_read_header(uschar *name, BOOL read_headers, BOOL subdir_set)
339{
8768d548 340FILE * fp = NULL;
4b4856ff
JH
341int n;
342int rcount = 0;
343long int uid, gid;
344BOOL inheader = FALSE;
4b4856ff
JH
345
346/* Reset all the global variables to their default values. However, there is
347one exception. DO NOT change the default value of dont_deliver, because it may
348be forced by an external setting. */
349
350spool_clear_header_globals();
6c1c3d1d 351
059ec3d9
PH
352/* Generate the full name and open the file. If message_subdir is already
353set, just look in the given directory. Otherwise, look in both the split
354and unsplit directories, as for the data file above. */
355
d7978c0f 356for (int n = 0; n < 2; n++)
059ec3d9
PH
357 {
358 if (!subdir_set)
59a93276 359 set_subdir_str(message_subdir, name, n);
41313d92 360
8768d548 361 if ((fp = Ufopen(spool_fname(US"input", message_subdir, name, US""), "rb")))
41313d92
JH
362 break;
363 if (n != 0 || subdir_set || errno != ENOENT)
364 return spool_read_notopen;
059ec3d9
PH
365 }
366
367errno = 0;
368
369#ifndef COMPILE_UTILITY
370DEBUG(D_deliver) debug_printf("reading spool file %s\n", name);
371#endif /* COMPILE_UTILITY */
372
373/* The first line of a spool file contains the message id followed by -H (i.e.
374the file name), in order to make the file self-identifying. */
375
8768d548 376if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
059ec3d9
PH
377if (Ustrlen(big_buffer) != MESSAGE_ID_LENGTH + 3 ||
378 Ustrncmp(big_buffer, name, MESSAGE_ID_LENGTH + 2) != 0)
379 goto SPOOL_FORMAT_ERROR;
380
381/* The next three lines in the header file are in a fixed format. The first
382contains the login, uid, and gid of the user who caused the file to be written.
ebb6e6d5
PH
383There are known cases where a negative gid is used, so we allow for both
384negative uids and gids. The second contains the mail address of the message's
385sender, enclosed in <>. The third contains the time the message was received,
386and the number of warning messages for delivery delays that have been sent. */
059ec3d9 387
8768d548 388if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
059ec3d9 389
870ce70e
JH
390 {
391 uschar *p = big_buffer + Ustrlen(big_buffer);
392 while (p > big_buffer && isspace(p[-1])) p--;
393 *p = 0;
394 if (!isdigit(p[-1])) goto SPOOL_FORMAT_ERROR;
395 while (p > big_buffer && (isdigit(p[-1]) || '-' == p[-1])) p--;
396 gid = Uatoi(p);
397 if (p <= big_buffer || *(--p) != ' ') goto SPOOL_FORMAT_ERROR;
398 *p = 0;
399 if (!isdigit(p[-1])) goto SPOOL_FORMAT_ERROR;
400 while (p > big_buffer && (isdigit(p[-1]) || '-' == p[-1])) p--;
401 uid = Uatoi(p);
402 if (p <= big_buffer || *(--p) != ' ') goto SPOOL_FORMAT_ERROR;
403 *p = 0;
404 }
8e669ac1 405
1e70f85b 406originator_login = string_copy(big_buffer);
059ec3d9
PH
407originator_uid = (uid_t)uid;
408originator_gid = (gid_t)gid;
409
e91ad4a7 410/* envelope from */
8768d548 411if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
059ec3d9
PH
412n = Ustrlen(big_buffer);
413if (n < 3 || big_buffer[0] != '<' || big_buffer[n-2] != '>')
414 goto SPOOL_FORMAT_ERROR;
415
f3ebb786 416sender_address = store_get(n-2, TRUE); /* tainted */
059ec3d9
PH
417Ustrncpy(sender_address, big_buffer+1, n-3);
418sender_address[n-3] = 0;
419
e91ad4a7 420/* time */
8768d548 421if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
32dfdf8b 422if (sscanf(CS big_buffer, TIME_T_FMT " %d", &received_time.tv_sec, &warning_count) != 2)
059ec3d9 423 goto SPOOL_FORMAT_ERROR;
32dfdf8b 424received_time.tv_usec = 0;
059ec3d9 425
32dfdf8b 426message_age = time(NULL) - received_time.tv_sec;
44416341
JH
427#ifndef COMPILE_UTILITY
428if (f.running_in_test_harness)
429 message_age = test_harness_fudged_queue_time(message_age);
430#endif
059ec3d9
PH
431
432#ifndef COMPILE_UTILITY
433DEBUG(D_deliver) debug_printf("user=%s uid=%ld gid=%ld sender=%s\n",
434 originator_login, (long int)originator_uid, (long int)originator_gid,
435 sender_address);
44416341 436#endif
059ec3d9 437
08955dd3
PH
438/* Now there may be a number of optional lines, each starting with "-". If you
439add a new setting here, make sure you set the default above.
059ec3d9 440
08955dd3
PH
441Because there are now quite a number of different possibilities, we use a
442switch on the first character to avoid too many failing tests. Thanks to Nico
443Erfurth for the patch that implemented this. I have made it even more efficient
444by not re-scanning the first two characters.
445
446To allow new versions of Exim that add additional flags to interwork with older
447versions that do not understand them, just ignore any lines starting with "-"
448that we don't recognize. Otherwise it wouldn't be possible to back off a new
f3ebb786
JH
449version that left new-style flags written on the spool.
450
451If the line starts with "--" the content of the variable is tainted. */
08955dd3 452
059ec3d9
PH
453for (;;)
454 {
e91ad4a7 455 int len;
f3ebb786
JH
456 BOOL tainted;
457 uschar * var;
fc55624d 458 const uschar * p;
f3ebb786 459
8768d548 460 if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
059ec3d9 461 if (big_buffer[0] != '-') break;
e91ad4a7
JH
462 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
463 && big_buffer[len-1] != '\n'
464 )
465 { /* buffer not big enough for line; certs make this possible */
466 uschar * buf;
467 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
f3ebb786 468 buf = store_get_perm(big_buffer_size *= 2, FALSE);
e91ad4a7
JH
469 memcpy(buf, big_buffer, --len);
470 big_buffer = buf;
8768d548 471 if (Ufgets(big_buffer+len, big_buffer_size-len, fp) == NULL)
e91ad4a7
JH
472 goto SPOOL_READ_ERROR;
473 }
474 big_buffer[len-1] = 0;
47ca6d6c 475
f3ebb786
JH
476 tainted = big_buffer[1] == '-';
477 var = big_buffer + (tainted ? 2 : 1);
478 p = var + 1;
479
480 switch(*var)
059ec3d9 481 {
08955dd3
PH
482 case 'a':
483
484 /* Nowadays we use "-aclc" and "-aclm" for the different types of ACL
485 variable, because Exim allows any number of them, with arbitrary names.
486 The line in the spool file is "-acl[cm] <name> <length>". The name excludes
487 the c or m. */
488
489 if (Ustrncmp(p, "clc ", 4) == 0 ||
490 Ustrncmp(p, "clm ", 4) == 0)
491 {
492 uschar *name, *endptr;
493 int count;
494 tree_node *node;
f3ebb786 495 endptr = Ustrchr(var + 5, ' ');
08955dd3 496 if (endptr == NULL) goto SPOOL_FORMAT_ERROR;
f3ebb786
JH
497 name = string_sprintf("%c%.*s", var[3],
498 (int)(endptr - var - 5), var + 5);
08955dd3
PH
499 if (sscanf(CS endptr, " %d", &count) != 1) goto SPOOL_FORMAT_ERROR;
500 node = acl_var_create(name);
f3ebb786 501 node->data.ptr = store_get(count + 1, tainted);
8768d548 502 if (fread(node->data.ptr, 1, count+1, fp) < count) goto SPOOL_READ_ERROR;
08955dd3
PH
503 ((uschar*)node->data.ptr)[count] = 0;
504 }
505
506 else if (Ustrcmp(p, "llow_unqualified_recipient") == 0)
8768d548 507 f.allow_unqualified_recipient = TRUE;
08955dd3 508 else if (Ustrcmp(p, "llow_unqualified_sender") == 0)
8768d548 509 f.allow_unqualified_sender = TRUE;
08955dd3
PH
510
511 else if (Ustrncmp(p, "uth_id", 6) == 0)
f3ebb786 512 authenticated_id = string_copy_taint(var + 8, tainted);
08955dd3 513 else if (Ustrncmp(p, "uth_sender", 10) == 0)
f3ebb786 514 authenticated_sender = string_copy_taint(var + 12, tainted);
08955dd3 515 else if (Ustrncmp(p, "ctive_hostname", 14) == 0)
f3ebb786 516 smtp_active_hostname = string_copy_taint(var + 16, tainted);
08955dd3
PH
517
518 /* For long-term backward compatibility, we recognize "-acl", which was
519 used before the number of ACL variables changed from 10 to 20. This was
520 before the subsequent change to an arbitrary number of named variables.
521 This code is retained so that upgrades from very old versions can still
522 handle old-format spool files. The value given after "-acl" is a number
523 that is 0-9 for connection variables, and 10-19 for message variables. */
524
525 else if (Ustrncmp(p, "cl ", 3) == 0)
526 {
4dc2379a
JH
527 unsigned index, count;
528 uschar name[20]; /* Need plenty of space for %u format */
529 tree_node * node;
f3ebb786 530 if ( sscanf(CS var + 4, "%u %u", &index, &count) != 2
806c3df9 531 || index >= 20
f267271d 532 || count > 16384 /* arbitrary limit on variable size */
806c3df9 533 )
08955dd3 534 goto SPOOL_FORMAT_ERROR;
8dce1a6f 535 if (index < 10)
4dc2379a 536 (void) string_format(name, sizeof(name), "%c%u", 'c', index);
806c3df9 537 else
4dc2379a 538 (void) string_format(name, sizeof(name), "%c%u", 'm', index - 10);
08955dd3 539 node = acl_var_create(name);
f3ebb786 540 node->data.ptr = store_get(count + 1, tainted);
f267271d
JH
541 /* We sanity-checked the count, so disable the Coverity error */
542 /* coverity[tainted_data] */
8768d548 543 if (fread(node->data.ptr, 1, count+1, fp) < count) goto SPOOL_READ_ERROR;
4dc2379a 544 (US node->data.ptr)[count] = '\0';
08955dd3
PH
545 }
546 break;
547
548 case 'b':
549 if (Ustrncmp(p, "ody_linecount", 13) == 0)
f3ebb786 550 body_linecount = Uatoi(var + 14);
08955dd3 551 else if (Ustrncmp(p, "ody_zerocount", 13) == 0)
f3ebb786 552 body_zerocount = Uatoi(var + 14);
e91ad4a7 553#ifdef EXPERIMENTAL_BRIGHTMAIL
08955dd3 554 else if (Ustrncmp(p, "mi_verdicts ", 12) == 0)
f3ebb786 555 bmi_verdicts = string_copy_taint(var + 13, tainted);
e91ad4a7 556#endif
08955dd3
PH
557 break;
558
559 case 'd':
560 if (Ustrcmp(p, "eliver_firsttime") == 0)
8768d548 561 f.deliver_firsttime = TRUE;
6c1c3d1d
WB
562 /* Check if the dsn flags have been set in the header file */
563 else if (Ustrncmp(p, "sn_ret", 6) == 0)
f3ebb786 564 dsn_ret= atoi(CS var + 7);
6c1c3d1d 565 else if (Ustrncmp(p, "sn_envid", 8) == 0)
f3ebb786 566 dsn_envid = string_copy_taint(var + 10, tainted);
08955dd3
PH
567 break;
568
569 case 'f':
570 if (Ustrncmp(p, "rozen", 5) == 0)
571 {
8768d548 572 f.deliver_freeze = TRUE;
f3ebb786 573 if (sscanf(CS var+6, TIME_T_FMT, &deliver_frozen_at) != 1)
dc8091e7 574 goto SPOOL_READ_ERROR;
08955dd3
PH
575 }
576 break;
577
578 case 'h':
579 if (Ustrcmp(p, "ost_lookup_deferred") == 0)
580 host_lookup_deferred = TRUE;
581 else if (Ustrcmp(p, "ost_lookup_failed") == 0)
582 host_lookup_failed = TRUE;
583 else if (Ustrncmp(p, "ost_auth", 8) == 0)
f3ebb786 584 sender_host_authenticated = string_copy_taint(var + 10, tainted);
08955dd3 585 else if (Ustrncmp(p, "ost_name", 8) == 0)
f3ebb786 586 sender_host_name = string_copy_taint(var + 10, tainted);
08955dd3 587 else if (Ustrncmp(p, "elo_name", 8) == 0)
f3ebb786 588 sender_helo_name = string_copy_taint(var + 10, tainted);
08955dd3
PH
589
590 /* We now record the port number after the address, separated by a
591 dot. For compatibility during upgrading, do nothing if there
592 isn't a value (it gets left at zero). */
593
594 else if (Ustrncmp(p, "ost_address", 11) == 0)
595 {
f3ebb786
JH
596 sender_host_port = host_address_extract_port(var + 13);
597 sender_host_address = string_copy_taint(var + 13, tainted);
08955dd3
PH
598 }
599 break;
600
601 case 'i':
602 if (Ustrncmp(p, "nterface_address", 16) == 0)
603 {
f3ebb786
JH
604 interface_port = host_address_extract_port(var + 18);
605 interface_address = string_copy_taint(var + 18, tainted);
08955dd3
PH
606 }
607 else if (Ustrncmp(p, "dent", 4) == 0)
f3ebb786 608 sender_ident = string_copy_taint(var + 6, tainted);
08955dd3
PH
609 break;
610
611 case 'l':
32dfdf8b 612 if (Ustrcmp(p, "ocal") == 0)
8768d548 613 f.sender_local = TRUE;
f3ebb786 614 else if (Ustrcmp(var, "localerror") == 0)
8768d548 615 f.local_error_message = TRUE;
9723f966 616#ifdef HAVE_LOCAL_SCAN
08955dd3 617 else if (Ustrncmp(p, "ocal_scan ", 10) == 0)
f3ebb786 618 local_scan_data = string_copy_taint(var + 11, tainted);
9723f966 619#endif
08955dd3
PH
620 break;
621
622 case 'm':
f3ebb786
JH
623 if (Ustrcmp(p, "anual_thaw") == 0)
624 f.deliver_manual_thaw = TRUE;
d677b2f2 625 else if (Ustrncmp(p, "ax_received_linelength", 22) == 0)
f3ebb786 626 max_received_linelength = Uatoi(var + 23);
08955dd3
PH
627 break;
628
629 case 'N':
8768d548 630 if (*p == 0) f.dont_deliver = TRUE; /* -N */
08955dd3
PH
631 break;
632
633 case 'r':
634 if (Ustrncmp(p, "eceived_protocol", 16) == 0)
f3ebb786 635 received_protocol = string_copy_taint(var + 18, tainted);
32dfdf8b
JH
636 else if (Ustrncmp(p, "eceived_time_usec", 17) == 0)
637 {
638 unsigned usec;
f3ebb786 639 if (sscanf(CS var + 20, "%u", &usec) == 1)
32dfdf8b
JH
640 received_time.tv_usec = usec;
641 }
08955dd3
PH
642 break;
643
644 case 's':
645 if (Ustrncmp(p, "ender_set_untrusted", 19) == 0)
8768d548 646 f.sender_set_untrusted = TRUE;
e91ad4a7 647#ifdef WITH_CONTENT_SCAN
3481c572 648 else if (Ustrncmp(p, "pam_bar ", 8) == 0)
f3ebb786 649 spam_bar = string_copy_taint(var + 9, tainted);
3481c572 650 else if (Ustrncmp(p, "pam_score ", 10) == 0)
f3ebb786 651 spam_score = string_copy_taint(var + 11, tainted);
08955dd3 652 else if (Ustrncmp(p, "pam_score_int ", 14) == 0)
f3ebb786 653 spam_score_int = string_copy_taint(var + 15, tainted);
e91ad4a7 654#endif
328c5688
JH
655#ifndef COMPILE_UTILITY
656 else if (Ustrncmp(p, "pool_file_wireformat", 20) == 0)
8768d548 657 f.spool_file_wireformat = TRUE;
328c5688 658#endif
8c5d388a 659#if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
7ade712c
JH
660 else if (Ustrncmp(p, "mtputf8", 7) == 0)
661 message_smtputf8 = TRUE;
662#endif
08955dd3
PH
663 break;
664
01603eec 665#ifndef DISABLE_TLS
08955dd3 666 case 't':
8ac90765
JH
667 if (Ustrncmp(p, "ls_", 3) == 0)
668 {
fc55624d 669 const uschar * q = p + 3;
8ac90765
JH
670 if (Ustrncmp(q, "certificate_verified", 20) == 0)
671 tls_in.certificate_verified = TRUE;
672 else if (Ustrncmp(q, "cipher", 6) == 0)
da40b1ec 673 tls_in.cipher = string_copy_taint(q+7, tainted);
e91ad4a7 674# ifndef COMPILE_UTILITY /* tls support fns not built in */
8ac90765 675 else if (Ustrncmp(q, "ourcert", 7) == 0)
da40b1ec 676 (void) tls_import_cert(q+8, &tls_in.ourcert);
8ac90765 677 else if (Ustrncmp(q, "peercert", 8) == 0)
da40b1ec 678 (void) tls_import_cert(q+9, &tls_in.peercert);
e91ad4a7 679# endif
8ac90765 680 else if (Ustrncmp(q, "peerdn", 6) == 0)
da40b1ec 681 tls_in.peerdn = string_unprinting(string_copy_taint(q+7, tainted));
8ac90765 682 else if (Ustrncmp(q, "sni", 3) == 0)
da40b1ec 683 tls_in.sni = string_unprinting(string_copy_taint(q+4, tainted));
8ac90765 684 else if (Ustrncmp(q, "ocsp", 4) == 0)
da40b1ec 685 tls_in.ocsp = q[5] - '0';
b10c87b3
JH
686# ifdef EXPERIMENTAL_TLS_RESUME
687 else if (Ustrncmp(q, "resumption", 10) == 0)
da40b1ec 688 tls_in.resumption = q[11] - 'A';
b10c87b3 689# endif
da40b1ec
JH
690 else if (Ustrncmp(q, "ver", 3) == 0)
691 tls_in.ver = string_copy_taint(q+4, tainted);
8ac90765 692 }
08955dd3 693 break;
e91ad4a7 694#endif
08955dd3 695
8c5d388a 696#if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
3c8b3577
JH
697 case 'u':
698 if (Ustrncmp(p, "tf8_downcvt", 11) == 0)
699 message_utf8_downconvert = 1;
0ec7e948 700 else if (Ustrncmp(p, "tf8_optdowncvt", 15) == 0)
3c8b3577
JH
701 message_utf8_downconvert = -1;
702 break;
703#endif
704
08955dd3
PH
705 default: /* Present because some compilers complain if all */
706 break; /* possibilities are not covered. */
059ec3d9 707 }
059ec3d9
PH
708 }
709
710/* Build sender_fullhost if required */
711
712#ifndef COMPILE_UTILITY
713host_build_sender_fullhost();
714#endif /* COMPILE_UTILITY */
715
716#ifndef COMPILE_UTILITY
717DEBUG(D_deliver)
8768d548 718 debug_printf("sender_local=%d ident=%s\n", f.sender_local,
d81d33cf 719 sender_ident ? sender_ident : US"unset");
059ec3d9
PH
720#endif /* COMPILE_UTILITY */
721
722/* We now have the tree of addresses NOT to deliver to, or a line
723containing "XX", indicating no tree. */
724
725if (Ustrncmp(big_buffer, "XX\n", 3) != 0 &&
8768d548 726 !read_nonrecipients_tree(&tree_nonrecipients, fp, big_buffer, big_buffer_size))
059ec3d9
PH
727 goto SPOOL_FORMAT_ERROR;
728
729#ifndef COMPILE_UTILITY
730DEBUG(D_deliver)
731 {
732 debug_printf("Non-recipients:\n");
733 debug_print_tree(tree_nonrecipients);
734 }
735#endif /* COMPILE_UTILITY */
736
737/* After reading the tree, the next line has not yet been read into the
d88f0784
JH
738buffer. It contains the count of recipients which follow on separate lines.
739Apply an arbitrary sanity check.*/
059ec3d9 740
8768d548 741if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
d88f0784
JH
742if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
743 goto SPOOL_FORMAT_ERROR;
059ec3d9
PH
744
745#ifndef COMPILE_UTILITY
746DEBUG(D_deliver) debug_printf("recipients_count=%d\n", rcount);
747#endif /* COMPILE_UTILITY */
748
749recipients_list_max = rcount;
f3ebb786 750recipients_list = store_get(rcount * sizeof(recipient_item), FALSE);
059ec3d9 751
d88f0784
JH
752/* We sanitised the count and know we have enough memory, so disable
753the Coverity error on recipients_count */
754/* coverity[tainted_data] */
755
059ec3d9
PH
756for (recipients_count = 0; recipients_count < rcount; recipients_count++)
757 {
758 int nn;
759 int pno = -1;
6c1c3d1d
WB
760 int dsn_flags = 0;
761 uschar *orcpt = NULL;
059ec3d9
PH
762 uschar *errors_to = NULL;
763 uschar *p;
764
8768d548 765 if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
059ec3d9
PH
766 nn = Ustrlen(big_buffer);
767 if (nn < 2) goto SPOOL_FORMAT_ERROR;
768
769 /* Remove the newline; this terminates the address if there is no additional
770 data on the line. */
771
772 p = big_buffer + nn - 1;
773 *p-- = 0;
774
775 /* Look back from the end of the line for digits and special terminators.
776 Since an address must end with a domain, we can tell that extra data is
777 present by the presence of the terminator, which is always some character
778 that cannot exist in a domain. (If I'd thought of the need for additional
779 data early on, I'd have put it at the start, with the address at the end. As
780 it is, we have to operate backwards. Addresses are permitted to contain
781 spaces, you see.)
782
783 This code has to cope with various versions of this data that have evolved
784 over time. In all cases, the line might just contain an address, with no
785 additional data. Otherwise, the possibilities are as follows:
786
787 Exim 3 type: <address><space><digits>,<digits>,<digits>
788
789 The second set of digits is the parent number for one_time addresses. The
790 other values were remnants of earlier experiments that were abandoned.
791
792 Exim 4 first type: <address><space><digits>
793
794 The digits are the parent number for one_time addresses.
795
796 Exim 4 new type: <address><space><data>#<type bits>
797
798 The type bits indicate what the contents of the data are.
799
800 Bit 01 indicates that, reading from right to left, the data
801 ends with <errors_to address><space><len>,<pno> where pno is
802 the parent number for one_time addresses, and len is the length
803 of the errors_to address (zero meaning none).
6c1c3d1d
WB
804
805 Bit 02 indicates that, again reading from right to left, the data continues
806 with orcpt len(orcpt),dsn_flags
059ec3d9
PH
807 */
808
809 while (isdigit(*p)) p--;
810
811 /* Handle Exim 3 spool files */
812
813 if (*p == ',')
814 {
815 int dummy;
f3ebb786
JH
816#if !defined (COMPILE_UTILITY)
817 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim 3 spool file\n");
818#endif
059ec3d9
PH
819 while (isdigit(*(--p)) || *p == ',');
820 if (*p == ' ')
821 {
822 *p++ = 0;
ff790e47 823 (void)sscanf(CS p, "%d,%d", &dummy, &pno);
059ec3d9
PH
824 }
825 }
826
827 /* Handle early Exim 4 spool files */
828
829 else if (*p == ' ')
830 {
f3ebb786
JH
831#if !defined (COMPILE_UTILITY)
832 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - early Exim 4 spool file\n");
833#endif
059ec3d9 834 *p++ = 0;
ff790e47 835 (void)sscanf(CS p, "%d", &pno);
059ec3d9
PH
836 }
837
838 /* Handle current format Exim 4 spool files */
839
840 else if (*p == '#')
841 {
842 int flags;
6c1c3d1d 843
50dc7409 844#if !defined (COMPILE_UTILITY)
df98a6ff 845 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim standard format spoolfile\n");
e91ad4a7 846#endif
6c1c3d1d 847
ff790e47 848 (void)sscanf(CS p+1, "%d", &flags);
059ec3d9
PH
849
850 if ((flags & 0x01) != 0) /* one_time data exists */
851 {
852 int len;
853 while (isdigit(*(--p)) || *p == ',' || *p == '-');
ff790e47 854 (void)sscanf(CS p+1, "%d,%d", &len, &pno);
059ec3d9
PH
855 *p = 0;
856 if (len > 0)
857 {
858 p -= len;
f3ebb786 859 errors_to = string_copy_taint(p, TRUE);
94431adb 860 }
6c1c3d1d
WB
861 }
862
863 *(--p) = 0; /* Terminate address */
6c1c3d1d
WB
864 if ((flags & 0x02) != 0) /* one_time data exists */
865 {
866 int len;
867 while (isdigit(*(--p)) || *p == ',' || *p == '-');
868 (void)sscanf(CS p+1, "%d,%d", &len, &dsn_flags);
869 *p = 0;
870 if (len > 0)
871 {
872 p -= len;
f3ebb786 873 orcpt = string_copy_taint(p, TRUE);
94431adb 874 }
059ec3d9
PH
875 }
876
877 *(--p) = 0; /* Terminate address */
6c1c3d1d 878 }
50dc7409 879#if !defined(COMPILE_UTILITY)
6c1c3d1d 880 else
e91ad4a7 881 { DEBUG(D_deliver) debug_printf("**** SPOOL_IN - No additional fields\n"); }
6c1c3d1d 882
df98a6ff
JH
883 if (orcpt || dsn_flags)
884 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: <%s> orcpt: <%s> dsn_flags: 0x%x\n",
6c1c3d1d 885 big_buffer, orcpt, dsn_flags);
df98a6ff
JH
886 if (errors_to)
887 DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: <%s> errorsto: <%s>\n",
6c1c3d1d 888 big_buffer, errors_to);
50dc7409 889#endif
059ec3d9 890
f3ebb786 891 recipients_list[recipients_count].address = string_copy_taint(big_buffer, TRUE);
059ec3d9
PH
892 recipients_list[recipients_count].pno = pno;
893 recipients_list[recipients_count].errors_to = errors_to;
6c1c3d1d
WB
894 recipients_list[recipients_count].orcpt = orcpt;
895 recipients_list[recipients_count].dsn_flags = dsn_flags;
059ec3d9
PH
896 }
897
898/* The remainder of the spool header file contains the headers for the message,
899separated off from the previous data by a blank line. Each header is preceded
900by a count of its length and either a certain letter (for various identified
901headers), space (for a miscellaneous live header) or an asterisk (for a header
902that has been rewritten). Count the Received: headers. We read the headers
903always, in order to check on the format of the file, but only create a header
904list if requested to do so. */
905
906inheader = TRUE;
8768d548 907if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
059ec3d9
PH
908if (big_buffer[0] != '\n') goto SPOOL_FORMAT_ERROR;
909
8768d548 910while ((n = fgetc(fp)) != EOF)
059ec3d9
PH
911 {
912 header_line *h;
913 uschar flag[4];
914 int i;
915
916 if (!isdigit(n)) goto SPOOL_FORMAT_ERROR;
8768d548 917 if(ungetc(n, fp) == EOF || fscanf(fp, "%d%c ", &n, flag) == EOF)
1ac6b2e7 918 goto SPOOL_READ_ERROR;
059ec3d9
PH
919 if (flag[0] != '*') message_size += n; /* Omit non-transmitted headers */
920
921 if (read_headers)
922 {
f3ebb786 923 h = store_get(sizeof(header_line), FALSE);
059ec3d9
PH
924 h->next = NULL;
925 h->type = flag[0];
926 h->slen = n;
f3ebb786 927 h->text = store_get(n+1, TRUE); /* tainted */
059ec3d9
PH
928
929 if (h->type == htype_received) received_count++;
930
d81d33cf
JH
931 if (header_list) header_last->next = h;
932 else header_list = h;
059ec3d9
PH
933 header_last = h;
934
935 for (i = 0; i < n; i++)
936 {
8768d548 937 int c = fgetc(fp);
059ec3d9
PH
938 if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
939 if (c == '\n' && h->type != htype_old) message_linecount++;
940 h->text[i] = c;
941 }
942 h->text[i] = 0;
943 }
944
945 /* Not requiring header data, just skip through the bytes */
946
947 else for (i = 0; i < n; i++)
948 {
8768d548 949 int c = fgetc(fp);
059ec3d9
PH
950 if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
951 }
952 }
953
954/* We have successfully read the data in the header file. Update the message
955line count by adding the body linecount to the header linecount. Close the file
956and give a positive response. */
957
958#ifndef COMPILE_UTILITY
959DEBUG(D_deliver) debug_printf("body_linecount=%d message_linecount=%d\n",
960 body_linecount, message_linecount);
961#endif /* COMPILE_UTILITY */
962
963message_linecount += body_linecount;
964
8768d548 965fclose(fp);
059ec3d9
PH
966return spool_read_OK;
967
968
969/* There was an error reading the spool or there was missing data,
970or there was a format error. A "read error" with no errno means an
971unexpected EOF, which we treat as a format error. */
972
973SPOOL_READ_ERROR:
974if (errno != 0)
975 {
976 n = errno;
977
e91ad4a7 978#ifndef COMPILE_UTILITY
059ec3d9 979 DEBUG(D_any) debug_printf("Error while reading spool file %s\n", name);
e91ad4a7 980#endif /* COMPILE_UTILITY */
059ec3d9 981
8768d548 982 fclose(fp);
059ec3d9 983 errno = n;
d81d33cf 984 return inheader ? spool_read_hdrerror : spool_read_enverror;
059ec3d9
PH
985 }
986
987SPOOL_FORMAT_ERROR:
988
989#ifndef COMPILE_UTILITY
990DEBUG(D_any) debug_printf("Format error in spool file %s\n", name);
991#endif /* COMPILE_UTILITY */
992
8768d548 993fclose(fp);
059ec3d9
PH
994errno = ERRNO_SPOOLFORMAT;
995return inheader? spool_read_hdrerror : spool_read_enverror;
996}
997
9d1c15ef
JH
998/* vi: aw ai sw=2
999*/
059ec3d9 1000/* End of spool_in.c */