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