diff --git a/mailman/configure.in b/mailman/configure.in index c368622..9573684 100644 --- a/mailman/configure.in +++ b/mailman/configure.in @@ -384,59 +384,29 @@ fi AC_MSG_RESULT($status) -# Now find the UIDs and GIDs -# Support --with-mail-gid and --with-cgi-gid -AC_MSG_CHECKING(for mail wrapper group; i.e. --with-mail-gid) -AC_ARG_WITH(mail-gid, dnl -[ --with-mail-gid group name mail programs run as]) -if test -z "$with_mail_gid" +# Support --with-mail-groupfile and --with-cgi-groupfile +AC_MSG_CHECKING(for mail wrapper group file; i.e. --with-mail-groupfile) +AC_ARG_WITH(mail-groupfile, dnl +[ --with-mail-groupfile file with group names mail programs run as]) +if test -z "$with_mail_groupfile" then - with_mail_gid="mailman other mail daemon" -fi -MM_FIND_GROUP_NAME(MAIL_GROUP, $with_mail_gid) -if test -z "$MAIL_GROUP" -then - if test "$with_permcheck" = "yes" - then - AC_MSG_ERROR([ -***** No group name \"$with_mail_gid\" found for the mail wrapper program. -***** This is the group that your mail server will use to run Mailman's -***** programs. You should specify an existing group with the -***** --with-mail-gid configure option, or use --without-permcheck to -***** skip this verification step. See also your mail server's documentation, -***** and Mailman's INSTALL file for details]) - else - MAIL_GROUP=$with_mail_gid - fi + with_mail_groupfile="$CONFIG_DIR/mail.groups" fi +MAIL_GROUP=$with_mail_groupfile AC_MSG_RESULT($MAIL_GROUP) +AC_SUBST(MAIL_GROUP) -AC_MSG_CHECKING(for CGI wrapper group; i.e. --with-cgi-gid) -AC_ARG_WITH(cgi-gid, dnl -[ --with-cgi-gid group name CGI programs run as]) -if test -z "$with_cgi_gid" +AC_MSG_CHECKING(for CGI wrapper group file; i.e. --with-cgi-groupfile) +AC_ARG_WITH(cgi-groupfile, dnl +[ --with-cgi-groupfile file with group names CGI programs run as]) +if test -z "$with_cgi_groupfile" then - with_cgi_gid="www www-data nobody" -fi - -MM_FIND_GROUP_NAME(CGI_GROUP, $with_cgi_gid) -if test -z "$CGI_GROUP" -then - if test "$with_permcheck" = "yes" - then - AC_MSG_ERROR([ -***** No group name \"$with_cgi_gid\" found for the CGI wrapper program. -***** This is the group that your web server will use to run Mailman's -***** programs. You should specify an existing group with the -***** --with-cgi-gid configure option, or use --without-permcheck to -***** skip this verification step. See also your web server's documentation, -***** and Mailman's INSTALL file for details]) - else - CGI_GROUP=$with_cgi_gid - fi + with_cgi_groupfile="$CONFIG_DIR/cgi.groups" fi +CGI_GROUP=$with_cgi_groupfile AC_MSG_RESULT($CGI_GROUP) +AC_SUBST(CGI_GROUP) # Check for CGI extensions, required by some Web servers @@ -530,7 +500,7 @@ fi # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(syslog.h) +AC_CHECK_HEADERS(syslog.h utmp.h utmpx.h) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T diff --git a/mailman/src/cgi-wrapper.c b/mailman/src/cgi-wrapper.c index 29d9ec5..04deb74 100644 --- a/mailman/src/cgi-wrapper.c +++ b/mailman/src/cgi-wrapper.c @@ -25,8 +25,8 @@ #define SCRIPTNAME SCRIPT #define LOG_IDENT "Mailman cgi-wrapper (" SCRIPT ")" -/* Group name that CGI scripts run as. See your web server's documentation - * for details. +/* File with group names that CGI scripts run as. + * See your web server's documentation for details. */ #define LEGAL_PARENT_GROUP CGI_GROUP diff --git a/mailman/src/common.h b/mailman/src/common.h index 451a156..d61537f 100644 --- a/mailman/src/common.h +++ b/mailman/src/common.h @@ -22,11 +22,17 @@ #ifdef HAVE_SYSLOG_H #include #endif /* HAVE_SYSLOG_H */ +#if HAVE_UTMPX_H +#include +#else +#include +#endif /* HAVE_UTMPX_H */ #include #include #include #include #include +#include #include /* GETGROUPS_T gets set in the makefile by configure */ diff --git a/mailman/src/mail-wrapper.c b/mailman/src/mail-wrapper.c index f268d5a..c5ff7da 100644 --- a/mailman/src/mail-wrapper.c +++ b/mailman/src/mail-wrapper.c @@ -20,8 +20,8 @@ #include "common.h" -/* Group name that your mail programs run as. See your mail server's - * documentation for details. +/* File with group names that your mail programs run as. + * See your mail server's documentation for details. */ #define LEGAL_PARENT_GROUP MAIL_GROUP diff --git a/mailman/src/common.c b/mailman/src/common.c index 62ed765..be3fd63 100644 --- a/mailman/src/common.c +++ b/mailman/src/common.c @@ -24,6 +24,8 @@ #define SCRIPTDIR PREFIX "/scripts/" /* trailing slash */ #define MODULEDIR PREFIX /* no trailing slash */ +#define MAX_GROUP_LEN 16 + const char* scriptdir = SCRIPTDIR; const char* moduledir = MODULEDIR; char* python = PYTHON; @@ -119,45 +121,83 @@ fatal(const char* ident, int exitcode, char* format, ...) void check_caller(const char* ident, const char* parentgroup) { - GID_T mygid = getgid(); - struct group *mygroup = getgrgid(mygid); +#if HAVE_UTMPX_H + struct utmpx ut; +#else + struct utmp ut; +#endif + size_t group_len, max_username_len = sizeof(ut.ut_user); + uid_t wrapper_uid = getuid(); + struct passwd *wrapper_pwd = NULL; + struct group *wrapper_grp = NULL; + struct group *server_grp = NULL; char* option; char* server; char* wrapper; + char groupname[MAX_GROUP_LEN + 1]; + char** member = NULL; + FILE *groupfile; + if (running_as_cgi) { - option = "--with-cgi-gid"; + option = "--with-cgi-groupfile"; server = "web"; wrapper = "CGI"; } else { - option = "--with-mail-gid"; + option = "--with-mail-groupfile"; server = "mail"; wrapper = "mail"; } - if (!mygroup) - fatal(ident, GROUP_NAME_NOT_FOUND, - "Failure to find group name for GID %d. Mailman\n" - "expected the %s wrapper to be executed as group\n" - "\"%s\", but the system's %s server executed the\n" - "wrapper as GID %d for which the name could not be\n" - "found. Try adding GID %d to your system as \"%s\",\n" - "or tweak your %s server to run the wrapper as group\n" - "\"%s\".", - mygid, wrapper, parentgroup, server, mygid, mygid, - parentgroup, server, parentgroup); - - if (strcmp(parentgroup, mygroup->gr_name)) - fatal(ident, GROUP_MISMATCH, + if ((wrapper_pwd = getpwuid(wrapper_uid)) == NULL) + fatal(ident, GROUP_NAME_NOT_FOUND, + "Failure to find password entry for UID %d.", wrapper_uid); + + if ((wrapper_grp = getgrgid(wrapper_pwd->pw_gid)) == NULL) + fatal(ident, GROUP_NAME_NOT_FOUND, + "Failure to find group name for GID %d.", wrapper_pwd->pw_gid); + + if ((groupfile = fopen(parentgroup, "r")) == NULL) + fatal(ident, GROUP_MISMATCH, + "Cannot open %s wrapper configuration file\n" + "\"%s\": %s\n" + "Check file permissions or re-run configure,\n" + "providing the command line option `%s=/path/to/file'", + wrapper, parentgroup, strerror(errno), option); + + while(fgets(groupname, MAX_GROUP_LEN + 1, groupfile) != NULL) { + group_len = strnlen(groupname, MAX_GROUP_LEN); + if (groupname[group_len - 1] == '\n') + groupname[group_len - 1] = '\0'; + server_grp = getgrnam(groupname); + if (server_grp != NULL) { + if(wrapper_pwd->pw_gid == server_grp->gr_gid) { + fclose(groupfile); + return; + } + member = server_grp->gr_mem; + while(member != NULL && *member != NULL) { + if(!strncmp(*member, wrapper_pwd->pw_name, max_username_len)) { + fclose(groupfile); + return; + } + member++; + } + } + } + fclose(groupfile); + fatal(ident, GROUP_MISMATCH, "Group mismatch error. Mailman expected the %s\n" - "wrapper script to be executed as group \"%s\", but\n" + "wrapper script to be executed as group listed in file\n" + "\"%s\", but\n" "the system's %s server executed the %s script as\n" - "group \"%s\". Try tweaking the %s server to run the\n" - "script as group \"%s\", or re-run configure, \n" - "providing the command line option `%s=%s'.", - wrapper, parentgroup, server, wrapper, mygroup->gr_name, - server, parentgroup, option, mygroup->gr_name); + "user \"%s\" that isn't member of any of those groups.\n" + "Try tweaking the %s server to run the %s script as one\n" + "of allowed groups, or add group \"%s\" to the file\n" + "\"%s\".", + wrapper, parentgroup, server, wrapper, wrapper_pwd->pw_name, + server, wrapper, wrapper_grp->gr_name, parentgroup); }