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