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 8c05848..a0cc6a8 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 943b3bd..be0fc0d 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 bd55514..7627fb7 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 2538c70..3258940 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 df6c57d..62ab83a 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 09b6461..c49a0ad 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 9a2da7a..091089f 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 e07186b..7c3ae4f 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 e1e3714..dda4897 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 ef18655..8d21a7f 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 c0c9438..c0fa960 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 bb5d90b..142d557 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 cedce6f..97d69db 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,12 +114,68 @@ 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 2307fc7..d417f35 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 bb8c6e0..3c915a4 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 5948000..b33ebb6 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