On 2012-02-19 at 15:06 +0100, Moritz Wilhelmy wrote: > I've installed mailman in a FreeBSD-jail(8) (much like chroot(8)-jails, > but can't be left that easily via fchdir etc.), and now I have the > problem that I can't reach mailman (version 2, version 3 would have > LMTP, which would eliminate the entire problem). Exim, trying to be > secure software is refusing to run the jail(8) command as root, which > means I am having a hard time to pass things into the jail via a pipe > transport. > > I see a few more or less ugly kludges around the problem: > > - make a setuid wrapper that runs mailman in the jail. > - run another exim instance in the jail as some kind of LMTP or SMTP > wrapper around mailman v2 > > Does someone know a better way (e.g. a designated LMTP wrapper > implementation)?
If you're using Jails for security, you might want to consider whether or not the MTA should run inside a jail too. As long as you're not doing so, try the patch (that's both below and attached). I don't currently have any Jails setup, so can't actually *test* it, but it does compile. *cough* On FreeBSD 7, and there may have been incompatible changes in later releases. This is relative to git head, but should apply back for a release or two without issues, I think. Please let me know how you get on, if you try it, so we can consider it for inclusion in the next release (and you don't get stuck maintaining a patch locally). Regards, -Phil From aac11fa66a9f4a2b7417d328bd9b0d59666bd7c5 Mon Sep 17 00:00:00 2001 From: Phil Pennock <[email protected]> Date: Mon, 20 Feb 2012 03:08:05 -0500 Subject: [PATCH] jail_identifier support for pipe transport --- src/OS/os.c-FreeBSD | 82 +++++++++++++++++++++++++++++++++++++++++++++ src/OS/os.h-FreeBSD | 9 +++++ src/src/transports/pipe.c | 53 +++++++++++++++++++++++++++-- src/src/transports/pipe.h | 1 + 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 src/OS/os.c-FreeBSD diff --git a/src/OS/os.c-FreeBSD b/src/OS/os.c-FreeBSD new file mode 100644 index 0000000..3b9fa14 --- /dev/null +++ b/src/OS/os.c-FreeBSD @@ -0,0 +1,82 @@ +#ifndef COMPILE_UTILITY /* Utilities don't need special code */ + +#ifdef HAVE_FREEBSD_JAIL + +#include <sys/sysctl.h> + +/* Given a string, search system jail list to find the jid for that string. + +Returns: + -1 unable to extract jail identifier + >= 0 jail identifier +*/ + +int +parse_jail_identifier(uschar *identifier) +{ +/* Logic borrowed from FreeBSD 7's src/usr.sbin/jls/jls.c */ +/* Later releases might permit matching on IPv6? */ +struct xprison *xp; +struct in_addr in; +size_t i, len; +int jid; +uschar *store_reset_point; + +if (!identifier) + return -1; + +if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1) + { + DEBUG(D_any) + debug_printf("PJI: sysctlbyname(): security.jail.list (1:len): %s\n", strerror(errno)); + return -1; + } +if (len < sizeof(*xp)) + { + DEBUG(D_any) + debug_printf("PJI: length too short, aborting for safety [%ld]\n", (long) len); + return -1; + } + +store_reset_point = store_get(0); +xp = (struct xprison *) store_get(len); +if (sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1) + { + DEBUG(D_any) + debug_printf("PJI: sysctlbyname(): security.jail.list (2:fetch): %s\n", strerror(errno)); + return -1; + } +if (len < sizeof(*xp) || len % sizeof(*xp) || + xp->pr_version != XPRISON_VERSION) + { + int i=0; + if (len >= sizeof(*xp)) + i = xp->pr_version; + DEBUG(D_any) + debug_printf("PJI: kernel ABI changed from Exim, not mutually compatible.\n" + " sizeof(struct xprison)=%ld len=%ld pr_version=%d XPRISON_VERSION=%d\n", + (long) sizeof(*xp), (long) len, i, XPRISON_VERSION); + return -1; + } + +jid = -1; +for (i = 0; i < len / sizeof(*xp); i++) + { + in.s_addr = ntohl(xp->pr_ip); + if (streqic(identifier, US xp->pr_host) || + streqic(identifier, US xp->pr_path) || + streqic(identifier, US inet_ntoa(in))) + { + jid = xp->pr_id; + break; + } + xp++; + } + +store_reset(store_reset_point); +return jid; +} +#endif /* HAVE_FREEBSD_JAIL */ + +/* vim: set ft=c : */ +#endif /* COMPILE_UTILITY */ diff --git a/src/OS/os.h-FreeBSD b/src/OS/os.h-FreeBSD index c5ed042..9ed2080 100644 --- a/src/OS/os.h-FreeBSD +++ b/src/OS/os.h-FreeBSD @@ -8,6 +8,15 @@ #define HAVE_SRANDOMDEV #define HAVE_ARC4RANDOM +#ifndef COMPILE_UTILITY +# if __FreeBSD__ >= 7 +# define HAVE_FREEBSD_JAIL +# include <sys/param.h> +# include <sys/jail.h> +int parse_jail_identifier(unsigned char *); +# endif +#endif + typedef struct flock flock_t; /* End */ diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c index 15714f3..e1000c9 100644 --- a/src/src/transports/pipe.c +++ b/src/src/transports/pipe.c @@ -43,6 +43,10 @@ optionlist pipe_transport_options[] = { (void *)offsetof(pipe_transport_options_block, freeze_signal) }, { "ignore_status", opt_bool, (void *)offsetof(pipe_transport_options_block, ignore_status) }, + #ifdef HAVE_FREEBSD_JAIL + { "jail_identifier", opt_stringptr, + (void *)offsetof(pipe_transport_options_block, jail_identifier) }, + #endif { "log_defer_output", opt_bool | opt_public, (void *)offsetof(transport_instance, log_defer_output) }, { "log_fail_output", opt_bool | opt_public, @@ -106,6 +110,7 @@ pipe_transport_options_block pipe_transport_option_defaults = { mac_expanded_string(EX_CANTCREAT), NULL, /* check_string */ NULL, /* escape_string */ + NULL, /* jail_identifier */ 022, /* umask */ 20480, /* max_output */ 60*60, /* timeout */ @@ -123,7 +128,6 @@ pipe_transport_options_block pipe_transport_option_defaults = { }; - /************************************************* * Setup entry point * *************************************************/ @@ -131,7 +135,8 @@ pipe_transport_options_block pipe_transport_option_defaults = { /* 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. It may also re-enable coredumps. +for the user. It may also re-enable coredumps. On FreeBSD, it might switch +into a jail. Arguments: tblock points to the transport instance @@ -158,6 +163,49 @@ gid = gid; errmsg = errmsg; ob = ob; +#ifdef HAVE_FREEBSD_JAIL +if (ob->jail_identifier) + { + int jrc, jid = -1; + long jtmp; + uschar *jail_str, *jend; + + jail_str = expand_string(ob->jail_identifier); + if (jail_str) + { + jtmp = Ustrtol(jail_str, &jend, 10); + if (jend == jail_str) + { + /* os.c provides this */ + jid = parse_jail_identifier(jail_str); + DEBUG(D_transport) + debug_printf("jail setup: jail identifier \"%s\" -> %d%s\n", + jail_str, jid, + jid < 0 ? " (IGNORED)" : ""); + } + else if (jtmp > INT_MAX || jtmp < 0) + { + log_write(0, LOG_MAIN, + "jail_identifier \"%s\" not integer >= 0", jail_str); + return DEFER; + } + else + jid = (int) jtmp; + } + + if (jid > -1) + { + jrc = jail_attach(jid); + if (jrc < 0) + { + log_write(0, LOG_MAIN, + "delivery jail_attach(%d) failed: %s", jid, strerror(errno)); + return DEFER; + } + } + } +#endif + #ifdef HAVE_SETCLASSRESOURCES if (ob->use_classresources) { @@ -196,7 +244,6 @@ return OK; } - /************************************************* * Initialization entry point * *************************************************/ diff --git a/src/src/transports/pipe.h b/src/src/transports/pipe.h index 343628e..ebee5e8 100644 --- a/src/src/transports/pipe.h +++ b/src/src/transports/pipe.h @@ -17,6 +17,7 @@ typedef struct { uschar *temp_errors; uschar *check_string; uschar *escape_string; + uschar *jail_identifier; int umask; int max_output; int timeout; -- 1.7.9
From aac11fa66a9f4a2b7417d328bd9b0d59666bd7c5 Mon Sep 17 00:00:00 2001 From: Phil Pennock <[email protected]> Date: Mon, 20 Feb 2012 03:08:05 -0500 Subject: [PATCH] jail_identifier support for pipe transport --- src/OS/os.c-FreeBSD | 82 +++++++++++++++++++++++++++++++++++++++++++++ src/OS/os.h-FreeBSD | 9 +++++ src/src/transports/pipe.c | 53 +++++++++++++++++++++++++++-- src/src/transports/pipe.h | 1 + 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 src/OS/os.c-FreeBSD diff --git a/src/OS/os.c-FreeBSD b/src/OS/os.c-FreeBSD new file mode 100644 index 0000000..3b9fa14 --- /dev/null +++ b/src/OS/os.c-FreeBSD @@ -0,0 +1,82 @@ +#ifndef COMPILE_UTILITY /* Utilities don't need special code */ + +#ifdef HAVE_FREEBSD_JAIL + +#include <sys/sysctl.h> + +/* Given a string, search system jail list to find the jid for that string. + +Returns: + -1 unable to extract jail identifier + >= 0 jail identifier +*/ + +int +parse_jail_identifier(uschar *identifier) +{ +/* Logic borrowed from FreeBSD 7's src/usr.sbin/jls/jls.c */ +/* Later releases might permit matching on IPv6? */ +struct xprison *xp; +struct in_addr in; +size_t i, len; +int jid; +uschar *store_reset_point; + +if (!identifier) + return -1; + +if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1) + { + DEBUG(D_any) + debug_printf("PJI: sysctlbyname(): security.jail.list (1:len): %s\n", strerror(errno)); + return -1; + } +if (len < sizeof(*xp)) + { + DEBUG(D_any) + debug_printf("PJI: length too short, aborting for safety [%ld]\n", (long) len); + return -1; + } + +store_reset_point = store_get(0); +xp = (struct xprison *) store_get(len); +if (sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1) + { + DEBUG(D_any) + debug_printf("PJI: sysctlbyname(): security.jail.list (2:fetch): %s\n", strerror(errno)); + return -1; + } +if (len < sizeof(*xp) || len % sizeof(*xp) || + xp->pr_version != XPRISON_VERSION) + { + int i=0; + if (len >= sizeof(*xp)) + i = xp->pr_version; + DEBUG(D_any) + debug_printf("PJI: kernel ABI changed from Exim, not mutually compatible.\n" + " sizeof(struct xprison)=%ld len=%ld pr_version=%d XPRISON_VERSION=%d\n", + (long) sizeof(*xp), (long) len, i, XPRISON_VERSION); + return -1; + } + +jid = -1; +for (i = 0; i < len / sizeof(*xp); i++) + { + in.s_addr = ntohl(xp->pr_ip); + if (streqic(identifier, US xp->pr_host) || + streqic(identifier, US xp->pr_path) || + streqic(identifier, US inet_ntoa(in))) + { + jid = xp->pr_id; + break; + } + xp++; + } + +store_reset(store_reset_point); +return jid; +} +#endif /* HAVE_FREEBSD_JAIL */ + +/* vim: set ft=c : */ +#endif /* COMPILE_UTILITY */ diff --git a/src/OS/os.h-FreeBSD b/src/OS/os.h-FreeBSD index c5ed042..9ed2080 100644 --- a/src/OS/os.h-FreeBSD +++ b/src/OS/os.h-FreeBSD @@ -8,6 +8,15 @@ #define HAVE_SRANDOMDEV #define HAVE_ARC4RANDOM +#ifndef COMPILE_UTILITY +# if __FreeBSD__ >= 7 +# define HAVE_FREEBSD_JAIL +# include <sys/param.h> +# include <sys/jail.h> +int parse_jail_identifier(unsigned char *); +# endif +#endif + typedef struct flock flock_t; /* End */ diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c index 15714f3..e1000c9 100644 --- a/src/src/transports/pipe.c +++ b/src/src/transports/pipe.c @@ -43,6 +43,10 @@ optionlist pipe_transport_options[] = { (void *)offsetof(pipe_transport_options_block, freeze_signal) }, { "ignore_status", opt_bool, (void *)offsetof(pipe_transport_options_block, ignore_status) }, + #ifdef HAVE_FREEBSD_JAIL + { "jail_identifier", opt_stringptr, + (void *)offsetof(pipe_transport_options_block, jail_identifier) }, + #endif { "log_defer_output", opt_bool | opt_public, (void *)offsetof(transport_instance, log_defer_output) }, { "log_fail_output", opt_bool | opt_public, @@ -106,6 +110,7 @@ pipe_transport_options_block pipe_transport_option_defaults = { mac_expanded_string(EX_CANTCREAT), NULL, /* check_string */ NULL, /* escape_string */ + NULL, /* jail_identifier */ 022, /* umask */ 20480, /* max_output */ 60*60, /* timeout */ @@ -123,7 +128,6 @@ pipe_transport_options_block pipe_transport_option_defaults = { }; - /************************************************* * Setup entry point * *************************************************/ @@ -131,7 +135,8 @@ pipe_transport_options_block pipe_transport_option_defaults = { /* 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. It may also re-enable coredumps. +for the user. It may also re-enable coredumps. On FreeBSD, it might switch +into a jail. Arguments: tblock points to the transport instance @@ -158,6 +163,49 @@ gid = gid; errmsg = errmsg; ob = ob; +#ifdef HAVE_FREEBSD_JAIL +if (ob->jail_identifier) + { + int jrc, jid = -1; + long jtmp; + uschar *jail_str, *jend; + + jail_str = expand_string(ob->jail_identifier); + if (jail_str) + { + jtmp = Ustrtol(jail_str, &jend, 10); + if (jend == jail_str) + { + /* os.c provides this */ + jid = parse_jail_identifier(jail_str); + DEBUG(D_transport) + debug_printf("jail setup: jail identifier \"%s\" -> %d%s\n", + jail_str, jid, + jid < 0 ? " (IGNORED)" : ""); + } + else if (jtmp > INT_MAX || jtmp < 0) + { + log_write(0, LOG_MAIN, + "jail_identifier \"%s\" not integer >= 0", jail_str); + return DEFER; + } + else + jid = (int) jtmp; + } + + if (jid > -1) + { + jrc = jail_attach(jid); + if (jrc < 0) + { + log_write(0, LOG_MAIN, + "delivery jail_attach(%d) failed: %s", jid, strerror(errno)); + return DEFER; + } + } + } +#endif + #ifdef HAVE_SETCLASSRESOURCES if (ob->use_classresources) { @@ -196,7 +244,6 @@ return OK; } - /************************************************* * Initialization entry point * *************************************************/ diff --git a/src/src/transports/pipe.h b/src/src/transports/pipe.h index 343628e..ebee5e8 100644 --- a/src/src/transports/pipe.h +++ b/src/src/transports/pipe.h @@ -17,6 +17,7 @@ typedef struct { uschar *temp_errors; uschar *check_string; uschar *escape_string; + uschar *jail_identifier; int umask; int max_output; int timeout; -- 1.7.9
pgphN5xWeEjnC.pgp
Description: PGP signature
-- ## List details at https://lists.exim.org/mailman/listinfo/exim-users ## Exim details at http://www.exim.org/ ## Please use the Wiki with this list - http://wiki.exim.org/
