X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f1e894f37fb99398f7447220925a915bd031491a..0a49a7a4f1090b6f1ce1d0f9d969804c9226b53e:/src/src/transports/pipe.c diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c index fe32e1267..35048258e 100644 --- a/src/src/transports/pipe.c +++ b/src/src/transports/pipe.c @@ -1,16 +1,20 @@ -/* $Cambridge: exim/src/src/transports/pipe.c,v 1.7 2005/06/27 14:29:44 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/pipe.c,v 1.14 2009/11/16 19:50:39 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2009 */ /* See the file NOTICE for conditions of use and distribution. */ #include "../exim.h" #include "pipe.h" +#ifdef HAVE_SETCLASSRESOURCES +#include +#endif + /* Options specific to the pipe transport. They must be in alphabetic @@ -71,6 +75,10 @@ optionlist pipe_transport_options[] = { (void *)offsetof(pipe_transport_options_block, umask) }, { "use_bsmtp", opt_bool, (void *)offsetof(pipe_transport_options_block, use_bsmtp) }, + #ifdef HAVE_SETCLASSRESOURCES + { "use_classresources", opt_bool, + (void *)offsetof(pipe_transport_options_block, use_classresources) }, + #endif { "use_crlf", opt_bool, (void *)offsetof(pipe_transport_options_block, use_crlf) }, { "use_shell", opt_bool, @@ -89,7 +97,7 @@ pipe_transport_options_block pipe_transport_option_defaults = { NULL, /* cmd */ NULL, /* allow_commands */ NULL, /* environment */ - US"/usr/bin", /* path */ + US"/bin:/usr/bin", /* path */ NULL, /* message_prefix (reset in init if not bsmtp) */ NULL, /* message_suffix (ditto) */ US mac_expanded_string(EX_TEMPFAIL) ":" /* temp_errors */ @@ -106,11 +114,67 @@ pipe_transport_options_block pipe_transport_option_defaults = { FALSE, /* timeout_defer */ FALSE, /* use_shell */ FALSE, /* use_bsmtp */ + FALSE, /* use_classresources */ FALSE /* use_crlf */ }; +/************************************************* +* Setup entry point * +*************************************************/ + +/* Called for each delivery in the privileged state, just before the uid/gid +are changed and the main entry point is called. In a system that supports the +login_cap facilities, this function is used to set the class resource limits +for the user. + +Arguments: + tblock points to the transport instance + addrlist addresses about to be delivered (not used) + dummy not used (doesn't pass back data) + uid the uid that will be set (not used) + gid the gid that will be set (not used) + errmsg where to put an error message + +Returns: OK, FAIL, or DEFER +*/ + +static int +pipe_transport_setup(transport_instance *tblock, address_item *addrlist, + transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg) +{ +pipe_transport_options_block *ob = + (pipe_transport_options_block *)(tblock->options_block); + +addrlist = addrlist; /* Keep compiler happy */ +dummy = dummy; +uid = uid; +gid = gid; +errmsg = errmsg; +ob = ob; + +#ifdef HAVE_SETCLASSRESOURCES +if (ob->use_classresources) + { + struct passwd *pw = getpwuid(uid); + if (pw != NULL) + { + login_cap_t *lc = login_getpwclass(pw); + if (lc != NULL) + { + setclassresources(lc); + login_close(lc); + } + } + } +#endif + +return OK; +} + + + /************************************************* * Initialization entry point * *************************************************/ @@ -125,6 +189,10 @@ pipe_transport_init(transport_instance *tblock) pipe_transport_options_block *ob = (pipe_transport_options_block *)(tblock->options_block); +/* Set up the setup entry point, to be called in the privileged state */ + +tblock->setup = pipe_transport_setup; + /* If pipe_as_creator is set, then uid/gid should not be set. */ if (tblock->deliver_as_creator && (tblock->uid_set || tblock->gid_set || @@ -856,6 +924,18 @@ if ((rc = child_close(pid, timeout)) != 0) "transport: %s%s", tblock->name, strerror(errno), tmsg); } + /* Since the transport_filter timed out we assume it has sent the child process + a malformed or incomplete data stream. Kill off the child process + and prevent checking its exit status as it will has probably exited in error. + This prevents the transport_filter timeout message from getting overwritten + by the exit error which is not the cause of the problem. */ + + else if (transport_filter_timed_out) + { + killpg(pid, SIGKILL); + kill(outpid, SIGKILL); + } + /* Either the process completed, but yielded a non-zero (necessarily positive) status, or the process was terminated by a signal (rc will contain the negation of the signal number). Treat killing by signal as failure unless