-/* $Cambridge: exim/src/src/exim.c,v 1.32 2006/02/10 16:29:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.39 2006/05/22 18:42:34 fanf2 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
+/*************************************************
+* Call fopen() with umask 777 and adjust mode *
+*************************************************/
+
+/* Exim runs with umask(0) so that files created with open() have the mode that
+is specified in the open() call. However, there are some files, typically in
+the spool directory, that are created with fopen(). They end up world-writeable
+if no precautions are taken. Although the spool directory is not accessible to
+the world, this is an untidiness. So this is a wrapper function for fopen()
+that sorts out the mode of the created file.
+
+Arguments:
+ filename the file name
+ options the fopen() options
+ mode the required mode
+
+Returns: the fopened FILE or NULL
+*/
+
+FILE *
+modefopen(uschar *filename, char *options, mode_t mode)
+{
+mode_t saved_umask = umask(0777);
+FILE *f = Ufopen(filename, options);
+(void)umask(saved_umask);
+if (f != NULL) (void)fchmod(fileno(f), mode);
+return f;
+}
+
+
+
+
/*************************************************
* Ensure stdin, stdout, and stderr exist *
*************************************************/
#if HAVE_IPV6
fprintf(f, " IPv6");
#endif
+#ifdef HAVE_SETCLASSRESOURCES
+ fprintf(f, " use_setclassresources");
+#endif
#ifdef SUPPORT_PAM
fprintf(f, " PAM");
#endif
message_id = message_id_external + 1;
message_id[0] = 0;
-/* Set the umask to zero so that any files that Exim creates are created
-with the modes that it specifies. */
+/* Set the umask to zero so that any files Exim creates using open() are
+created with the modes that it specifies. NOTE: Files created with fopen() have
+a problem, which was not recognized till rather late (February 2006). With this
+umask, such files will be world writeable. (They are all content scanning files
+in the spool directory, which isn't world-accessible, so this is not a
+disaster, but it's untidy.) I don't want to change this overall setting,
+however, because it will interact badly with the open() calls. Instead, there's
+now a function called modefopen() that fiddles with the umask while calling
+fopen(). */
-umask(0);
+(void)umask(0);
/* Precompile the regular expression for matching a message id. Keep this in
step with the code that generates ids in the accept.c module. We need to do
except when starting the daemon or doing some kind of delivery or address
testing (-bt). These are the only cases when root need to be retained. We run
as exim for -bv and -bh. However, if deliver_drop_privilege is set, root is
-retained only for starting the daemon. */
+retained only for starting the daemon. We always do the initgroups() in this
+situation (controlled by the TRUE below), in order to be as close as possible
+to the state Exim usually runs in. */
if (!unprivileged && /* originally had root AND */
!removed_privilege && /* still got root AND */
)
))
{
- exim_setugid(exim_uid, exim_gid, FALSE, US"privilege not needed");
+ exim_setugid(exim_uid, exim_gid, TRUE, US"privilege not needed");
}
/* When we are retaining a privileged uid, we still change to the exim gid. */
return EXIT_FAILURE;
}
- /* For the rcpt_4xx errors, a value of 255 means "any", and a code > 100 as
- an error is for matching codes to the decade. Turn them into a real error
- code, off the decade. */
+ /* For the {MAIL,RCPT,DATA}_4xx errors, a value of 255 means "any", and a
+ code > 100 as an error is for matching codes to the decade. Turn them into
+ a real error code, off the decade. */
- if (basic_errno == ERRNO_RCPT4XX)
+ if (basic_errno == ERRNO_MAIL4XX ||
+ basic_errno == ERRNO_RCPT4XX ||
+ basic_errno == ERRNO_DATA4XX)
{
int code = (more_errno >> 8) & 255;
if (code == 255)
close_unwanted(); /* Close unwanted file descriptors and TLS */
exim_nullstd(); /* Ensure std{in,out,err} exist */
- /* Occasionally in the test harness we don't have synchronous delivery
- set (can happen with bounces). In that case, let the old process finish
- before continuing, to keep the debug output the same. */
-
- if (running_in_test_harness && !synchronous_delivery) millisleep(100);
-
/* Re-exec Exim if we need to regain privilege (note: in mua_wrapper
mode, deliver_drop_privilege is forced TRUE). */