Add support for setclassresources() in the pipe transport on FreeBSD,
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 21 Feb 2006 16:24:19 +0000 (16:24 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 21 Feb 2006 16:24:19 +0000 (16:24 +0000)
NetBSD, and BSDI (aka BSD/OS).

16 files changed:
doc/doc-misc/WishList
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/OS/Makefile-BSDI
src/OS/os.Configuring
src/OS/os.h-BSDI
src/OS/os.h-FreeBSD
src/OS/os.h-NetBSD
src/src/deliver.c
src/src/exim.c
src/src/structs.h
src/src/transports/appendfile.c
src/src/transports/pipe.c
src/src/transports/pipe.h
src/src/transports/smtp.c
src/src/verify.c

index 8c058484ca86fca804e1648ae52807fae17db9c2..a0cc6a854d89cc895165a28ad51469041b7f813b 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-misc/WishList,v 1.58 2006/02/13 15:09:30 ph10 Exp $
+$Cambridge: exim/doc/doc-misc/WishList,v 1.59 2006/02/21 16:24:19 ph10 Exp $
 
 EXIM 4 WISH LIST
 ----------------
@@ -2017,15 +2017,5 @@ It seems that there are clients that send AUTH when it hasn't been advertised,
 some even after HELO, not even EHLO. Sigh. Possibly this should be an ACL
 control, to enable it to be restricted to certain hosts.
 ------------------------------------------------------------------------------
-
-(349) 13-Feb-06 S Add login_cap support to the pipe transport
-
-FreeBSD (and maybe others) have some functions for a per-user resource database
-of which login_cap() is one. A copile-time macro (set for FreeBSD) could enable
-a new pipe transport option to cause setclassresources() to be called to limit
-the resources used. It's a bit tricky, because it has to be done as root, but
-in the forked transport process. There will have to be some higher-level code
-to deal with this.
-------------------------------------------------------------------------------
 --- HWM 349 ------------------------------------------------------------------
 ---------------------------- End of WishList ---------------------------------
index 943b3bd8b677891d16f48daa98b87f3229838ae5..be0fc0dac0e395a5a7fa5de842c2a644287d5861 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.308 2006/02/20 16:31:48 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.309 2006/02/21 16:24:19 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -207,6 +207,9 @@ JJ/05 exipick: Fixed bug where -bpc always showed a count of all messages
 
 PH/40 Changed the default ident timeout from 30s to 5s.
 
+PH/41 Added support for the use of login_cap features, on those BSD systems
+      that have them, for controlling the resources used by pipe deliveries.
+
 
 Exim version 4.60
 -----------------
index bd55514f192b6622f71e80c27c52951a73d877ad..7627fb7f9b517cb68ae8757e3edac8847731becf 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.87 2006/02/20 16:31:48 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.88 2006/02/21 16:24:19 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -62,6 +62,12 @@ PH/08 The default for dns_check_names_pattern now allows slashes within names,
 
 PH/09 The default for rfc4131_query_timeout has been changed from 30s to 5s.
 
+PH/10 When compiled on FreeBSD, NetBSD, or BSD/OS, the pipe transport has a new
+      Boolean option called use_classresources, defaulting false. If it is set
+      true, the setclassresources() function is used to set resource limits
+      when a pipe transport is run to perform a delivery. The limits for the
+      uid under which the pipe is to run are obtained from the login class
+      database.
 
 
 Version 4.60
index 2538c707e475917ec922bd4216fe9653b98ba033..3258940d0a034e45575f8b6dc7042c8eef189409 100644 (file)
@@ -1,6 +1,6 @@
-# $Cambridge: exim/src/OS/Makefile-BSDI,v 1.2 2005/05/23 16:58:55 fanf2 Exp $
+# $Cambridge: exim/src/OS/Makefile-BSDI,v 1.3 2006/02/21 16:24:19 ph10 Exp $
 
-# Exim: OS-specific make file for BSDI. Its antique link editor
+# Exim: OS-specific make file for BSDI aka BSD/OS. Its antique link editor
 # cannot handle the TextPop overriding.
 
 CFLAGS=-O
index df6c57d8ddd5ca1d3ec3e66a9e3e441392a1188c..62ab83a15fbcda27cb4e02e72fcb2072cff58b0c 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/src/OS/os.Configuring,v 1.1 2004/10/06 15:07:39 ph10 Exp $
+$Cambridge: exim/src/OS/os.Configuring,v 1.2 2006/02/21 16:24:19 ph10 Exp $
 
 Configuring Exim for different Operating Systems
 ------------------------------------------------
@@ -184,6 +184,13 @@ One OS does not have the sys/resource.h header. If NO_SYS_RESOURCE_H is defined
 in an os.h-<ostype> file, then the #include for this header is skipped in
 exim.h.
 
+Support for login_cap functions
+-------------------------------
+
+Some of the BSD systems support functions for controlling the resources that
+user processes can use (e.g. login_getpwclass). If HAVE_LOGIN_CAP is defined,
+Exim supports this feature for running pipe deliveries.
+
 The crypt_h header
 ------------------
 
index 09b646197ed6897749359b063f4e532139bb8f66..c49a0ad864305c602a9e23bae22aa653a5d13bc0 100644 (file)
@@ -1,8 +1,9 @@
-/* $Cambridge: exim/src/OS/os.h-BSDI,v 1.1 2004/10/06 15:07:39 ph10 Exp $ */
+/* $Cambridge: exim/src/OS/os.h-BSDI,v 1.2 2006/02/21 16:24:19 ph10 Exp $ */
 
 /* Exim: OS-specific C header file for BSDI */
 
 #define HAVE_BSD_GETLOADAVG
+#define HAVE_LOGIN_CAP
 #define HAVE_MMAP
 #define HAVE_SYS_MOUNT_H
 #define SIOCGIFCONF_GIVES_ADDR
index 9a2da7a5afbaa896bce6cf1d029c4bad5e205494..091089f52ccc53f90a4ce162717d60b3c2500c0d 100644 (file)
@@ -1,8 +1,9 @@
-/* $Cambridge: exim/src/OS/os.h-FreeBSD,v 1.1 2004/10/06 15:07:39 ph10 Exp $ */
+/* $Cambridge: exim/src/OS/os.h-FreeBSD,v 1.2 2006/02/21 16:24:19 ph10 Exp $ */
 
 /* Exim: OS-specific C header file for FreeBSD */
 
 #define HAVE_BSD_GETLOADAVG
+#define HAVE_LOGIN_CAP
 #define HAVE_MMAP
 #define HAVE_SYS_MOUNT_H
 #define SIOCGIFCONF_GIVES_ADDR
index e07186bf38f30373e4ca79877ce852e867574655..7c3ae4f5ead950fea84972868cfc4e5b637c2fb0 100644 (file)
@@ -1,8 +1,9 @@
-/* $Cambridge: exim/src/OS/os.h-NetBSD,v 1.1 2004/10/06 15:07:39 ph10 Exp $ */
+/* $Cambridge: exim/src/OS/os.h-NetBSD,v 1.2 2006/02/21 16:24:19 ph10 Exp $ */
 
 /* Exim: OS-specific C header file for NetBSD */
 
 #define HAVE_BSD_GETLOADAVG
+#define HAVE_LOGIN_CAP
 #define HAVE_MMAP
 #define HAVE_SYS_MOUNT_H
 #define SIOCGIFCONF_GIVES_ADDR
index e1e3714cc78ff1194c848c26ab49104ebe084eb2..dda4897b9a762a229e2a0dc2c04d7422b37dcda9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/deliver.c,v 1.28 2006/02/08 16:10:46 ph10 Exp $ */
+/* $Cambridge: exim/src/src/deliver.c,v 1.29 2006/02/21 16:24:19 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1743,7 +1743,7 @@ if ((pid = fork()) == 0)
 
   if (addr->transport->setup != NULL)
     {
-    switch((addr->transport->setup)(addr->transport, addr, NULL,
+    switch((addr->transport->setup)(addr->transport, addr, NULL, uid, gid,
            &(addr->message)))
       {
       case DEFER:
@@ -3617,12 +3617,25 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
     else return_path = new_return_path;
     }
 
+  /* Find the uid, gid, and use_initgroups setting for this transport. Failure
+  logs and sets up error messages, so we just post-process and continue with
+  the next address. */
+
+  if (!findugid(addr, tp, &uid, &gid, &use_initgroups))
+    {
+    remote_post_process(addr, LOG_MAIN|LOG_PANIC, NULL, fallback);
+    continue;
+    }
+
   /* If this transport has a setup function, call it now so that it gets
   run in this process and not in any subprocess. That way, the results of
-  any setup that are retained by the transport can be reusable. */
+  any setup that are retained by the transport can be reusable. One of the
+  things the setup does is to set the fallback host lists in the addresses.
+  That is why it is called at this point, before the continue delivery
+  processing, because that might use the fallback hosts. */
 
   if (tp->setup != NULL)
-    (void)((tp->setup)(addr->transport, addr, NULL, NULL));
+    (void)((tp->setup)(addr->transport, addr, NULL, uid, gid, NULL));
 
   /* If this is a run to continue delivery down an already-established
   channel, check that this set of addresses matches the transport and
@@ -3698,16 +3711,6 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
 
   transport_filter_argv = NULL;
 
-  /* Find the uid, gid, and use_initgroups setting for this transport. Failure
-  logs and sets up error messages, so we just post-process and continue with
-  the next address. */
-
-  if (!findugid(addr, tp, &uid, &gid, &use_initgroups))
-    {
-    remote_post_process(addr, LOG_MAIN|LOG_PANIC, NULL, fallback);
-    continue;
-    }
-
   /* Create the pipe for inter-process communication. If pipe creation
   fails, it is probably because the value of remote_max_parallel is so
   large that too many file descriptors for pipes have been created. Arrange
index ef18655416fc120a1d69c51cc0a6c80d40997040..8d21a7f9d8fd4242b3b42d7a977142e6f22c7b26 100644 (file)
@@ -1,4 +1,4 @@
-/* $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.34 2006/02/21 16:24:19 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -842,6 +842,9 @@ fprintf(f, "Support for:");
 #if HAVE_IPV6
   fprintf(f, " IPv6");
 #endif
+#ifdef HAVE_LOGIN_CAP
+  fprintf(f, " use_classresources");
+#endif
 #ifdef SUPPORT_PAM
   fprintf(f, " PAM");
 #endif
index c0c94388f3ef972fbde04b58864a758816a0a473..c0fa960d3fccfda9f2b38fa96b0b3b5be5aa7ea2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/structs.h,v 1.9 2006/02/07 11:19:00 ph10 Exp $ */
+/* $Cambridge: exim/src/src/structs.h,v 1.10 2006/02/21 16:24:19 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -138,6 +138,8 @@ typedef struct transport_instance {
     struct transport_instance *,
     struct address_item *,
     struct transport_feedback *,  /* For passing back config data */
+    uid_t,                        /* The uid that will be used */
+    gid_t,                        /* The gid that will be used */
     uschar **);                   /* For an error message */
                                   /**************************************/
   int     batch_max;              /* )                                  */
index bb5d90bcb6b182be46d28882ef98f859dd3a3588..142d5570399d9213d1d53166b01d20fba6238eba 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.12 2006/02/10 16:29:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.13 2006/02/21 16:24:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -247,6 +247,8 @@ 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
@@ -254,7 +256,7 @@ Returns:     OK, FAIL, or DEFER
 
 static int
 appendfile_transport_setup(transport_instance *tblock, address_item *addrlist,
-  transport_feedback *dummy, uschar **errmsg)
+  transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
 {
 appendfile_transport_options_block *ob =
   (appendfile_transport_options_block *)(tblock->options_block);
@@ -264,6 +266,8 @@ int i;
 
 addrlist = addrlist;    /* Keep picky compilers happy */
 dummy = dummy;
+uid = uid;
+gid = gid;
 
 /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size,
 mailbox_filecount */
index cedce6fd926f93678d7a514c618a9f21b52c1462..97d69db0feb64a3653f3412c971fa8aa6309e55a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/pipe.c,v 1.9 2006/02/07 11:19:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/pipe.c,v 1.10 2006/02/21 16:24:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 #include "../exim.h"
 #include "pipe.h"
 
+#ifdef HAVE_LOGIN_CAP
+#include <login_cap.h>
+#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_LOGIN_CAP
+  { "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,
@@ -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_LOGIN_CAP
+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 ||
index 2307fc7d5e45e76f68a4ae8d9f924db1b1362650..d417f35b1fd59dd36147bea3042148cf546a6c8d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/pipe.h,v 1.4 2006/02/07 11:19:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/pipe.h,v 1.5 2006/02/21 16:24:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -29,6 +29,7 @@ typedef struct {
   BOOL  timeout_defer;
   BOOL  use_shell;
   BOOL  use_bsmtp;
+  BOOL  use_classresources;
   BOOL  use_crlf;
 } pipe_transport_options_block;
 
index bb8c6e01821902575690c7b9da94cd6ec31c149c..3c915a4e1df5704f6812ae3a800a8c2ee882a139 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/smtp.c,v 1.20 2006/02/07 11:19:03 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/smtp.c,v 1.21 2006/02/21 16:24:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -207,6 +207,8 @@ Arguments:
   tblock    pointer to the transport instance block
   addrlist  list of addresses about to be transported
   tf        if not NULL, pointer to block in which to return options
+  uid       the uid that will be set (not used)
+  gid       the gid that will be set (not used)
   errmsg    place for error message (not used)
 
 Returns:  OK always (FAIL, DEFER not used)
@@ -214,12 +216,14 @@ Returns:  OK always (FAIL, DEFER not used)
 
 static int
 smtp_transport_setup(transport_instance *tblock, address_item *addrlist,
-  transport_feedback *tf, uschar **errmsg)
+  transport_feedback *tf, uid_t uid, gid_t gid, uschar **errmsg)
 {
 smtp_transport_options_block *ob =
   (smtp_transport_options_block *)(tblock->options_block);
 
 errmsg = errmsg;    /* Keep picky compilers happy */
+uid = uid;
+gid = gid;
 
 /* Pass back options if required. This interface is getting very messy. */
 
index 5948000c2c0fc84efe7d45e4e8246dc77af5158d..b33ebb6df9558821176fc2aafeefed040942d18b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/verify.c,v 1.33 2006/02/14 15:56:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.34 2006/02/21 16:24:19 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1051,7 +1051,7 @@ while (addr_new != NULL)
 
       if (addr->transport != NULL && !addr->transport->info->local)
         {
-        (void)(addr->transport->setup)(addr->transport, addr, &tf, NULL);
+        (void)(addr->transport->setup)(addr->transport, addr, &tf, 0, 0, NULL);
 
         /* If the transport has hosts and the router does not, or if the
         transport is configured to override the router's hosts, we must build a