X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/9242a7e8cfa94bbc9dd7eca6bd651b569b871c4e..85defcf0e9e4187107b8a1a5138ef9590ac3892c:/src/src/spool_in.c diff --git a/src/src/spool_in.c b/src/src/spool_in.c index 2a99c63dd..cd74d1ee7 100644 --- a/src/src/spool_in.c +++ b/src/src/spool_in.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for reading spool files. When compiling for a utility (eximon), @@ -57,9 +57,17 @@ for (i = 0; i < 2; i++) fname = spool_fname(US"input", message_subdir, id, US"-D"); DEBUG(D_deliver) debug_printf("Trying spool file %s\n", fname); + /* We protect against symlink attacks both in not propagating the + * file-descriptor to other processes as we exec, and also ensuring that we + * don't even open symlinks. + * No -D file inside the spool area should be a symlink. + */ if ((fd = Uopen(fname, #ifdef O_CLOEXEC O_CLOEXEC | +#endif +#ifdef O_NOFOLLOW + O_NOFOLLOW | #endif O_RDWR | O_APPEND, 0)) >= 0) break; @@ -206,49 +214,13 @@ return TRUE; -/************************************************* -* Read spool header file * -*************************************************/ - -/* This function reads a spool header file and places the data into the -appropriate global variables. The header portion is always read, but header -structures are built only if read_headers is set true. It isn't, for example, -while generating -bp output. - -It may be possible for blocks of nulls (binary zeroes) to get written on the -end of a file if there is a system crash during writing. It was observed on an -earlier version of Exim that omitted to fsync() the files - this is thought to -have been the cause of that incident, but in any case, this code must be robust -against such an event, and if such a file is encountered, it must be treated as -malformed. - -As called from deliver_message() (at least) we are running as root. - -Arguments: - name name of the header file, including the -H - read_headers TRUE if in-store header structures are to be built - subdir_set TRUE is message_subdir is already set - -Returns: spool_read_OK success - spool_read_notopen open failed - spool_read_enverror error in the envelope portion - spool_read_hdrerror error in the header portion -*/ - -int -spool_read_header(uschar *name, BOOL read_headers, BOOL subdir_set) -{ -FILE *f = NULL; -int n; -int rcount = 0; -long int uid, gid; -BOOL inheader = FALSE; -uschar *p; - /* Reset all the global variables to their default values. However, there is one exception. DO NOT change the default value of dont_deliver, because it may be forced by an external setting. */ +void +spool_clear_header_globals(void) +{ acl_var_c = acl_var_m = NULL; authenticated_id = NULL; authenticated_sender = NULL; @@ -267,7 +239,9 @@ host_lookup_failed = FALSE; interface_address = NULL; interface_port = 0; local_error_message = FALSE; +#ifdef HAVE_LOCAL_SCAN local_scan_data = NULL; +#endif max_received_linelength = 0; message_linecount = 0; received_protocol = NULL; @@ -297,12 +271,12 @@ bmi_verdicts = NULL; #ifndef DISABLE_DKIM dkim_signers = NULL; dkim_disable_verify = FALSE; -dkim_collect_input = FALSE; +dkim_collect_input = 0; #endif #ifdef SUPPORT_TLS tls_in.certificate_verified = FALSE; -# ifdef EXPERIMENTAL_DANE +# ifdef SUPPORT_DANE tls_in.dane_verified = FALSE; # endif tls_in.cipher = NULL; @@ -328,6 +302,53 @@ message_utf8_downconvert = 0; dsn_ret = 0; dsn_envid = NULL; +} + + +/************************************************* +* Read spool header file * +*************************************************/ + +/* This function reads a spool header file and places the data into the +appropriate global variables. The header portion is always read, but header +structures are built only if read_headers is set true. It isn't, for example, +while generating -bp output. + +It may be possible for blocks of nulls (binary zeroes) to get written on the +end of a file if there is a system crash during writing. It was observed on an +earlier version of Exim that omitted to fsync() the files - this is thought to +have been the cause of that incident, but in any case, this code must be robust +against such an event, and if such a file is encountered, it must be treated as +malformed. + +As called from deliver_message() (at least) we are running as root. + +Arguments: + name name of the header file, including the -H + read_headers TRUE if in-store header structures are to be built + subdir_set TRUE is message_subdir is already set + +Returns: spool_read_OK success + spool_read_notopen open failed + spool_read_enverror error in the envelope portion + spool_read_hdrerror error in the header portion +*/ + +int +spool_read_header(uschar *name, BOOL read_headers, BOOL subdir_set) +{ +FILE *f = NULL; +int n; +int rcount = 0; +long int uid, gid; +BOOL inheader = FALSE; +uschar *p; + +/* Reset all the global variables to their default values. However, there is +one exception. DO NOT change the default value of dont_deliver, because it may +be forced by an external setting. */ + +spool_clear_header_globals(); /* Generate the full name and open the file. If message_subdir is already set, just look in the given directory. Otherwise, look in both the split @@ -578,8 +599,10 @@ for (;;) sender_local = TRUE; else if (Ustrcmp(big_buffer, "-localerror") == 0) local_error_message = TRUE; +#ifdef HAVE_LOCAL_SCAN else if (Ustrncmp(p, "ocal_scan ", 10) == 0) local_scan_data = string_copy(big_buffer + 12); +#endif break; case 'm':