-/* $Cambridge: exim/src/src/exim.c,v 1.33 2006/02/16 10:05:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.c,v 1.41 2006/07/13 13:53:33 ph10 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
regex_ismsgid =
regex_must_compile(US"^(?:[^\\W_]{6}-){2}[^\\W_]{2}$", FALSE, TRUE);
+/* Precompile the regular expression that is used for matching an SMTP error
+code, possibly extended, at the start of an error message. */
+
+regex_smtp_code =
+ regex_must_compile(US"^\\d\\d\\d\\s(?:\\d\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\s)?",
+ FALSE, TRUE);
+
/* If the program is called as "mailq" treat it as equivalent to "exim -bp";
this seems to be a generally accepted convention, since one finds symbolic
links called "mailq" in standard OS configurations. */
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)
}
}
-/* Otherwise, set up the input size limit here */
+/* Otherwise, set up the input size limit here. */
else
{
}
}
+ /* Run the acl_not_smtp_start ACL if required. The result of the ACL is
+ ignored; rejecting here would just add complication, and it can just as
+ well be done later. Allow $recipients to be visible in the ACL. */
+
+ if (acl_not_smtp_start != NULL)
+ {
+ uschar *user_msg, *log_msg;
+ enable_dollar_recipients = TRUE;
+ (void)acl_check(ACL_WHERE_NOTSMTP_START, NULL, acl_not_smtp_start,
+ &user_msg, &log_msg);
+ enable_dollar_recipients = FALSE;
+ }
+
/* Read the data for the message. If filter_test is not FTEST_NONE, this
will just read the headers for the message, and not write anything onto the
spool. */