diff options
| author | bwarsaw | 1998-05-26 18:42:44 +0000 |
|---|---|---|
| committer | bwarsaw | 1998-05-26 18:42:44 +0000 |
| commit | 4b77f88dc96acf9e971908c1badf3305ee618ca1 (patch) | |
| tree | c425088f9db12fb3f826136f167be5cdc77a9bb4 /src | |
| parent | a38041fa64fb30b661a9a55a6c9a3c313ba453a4 (diff) | |
| download | mailman-4b77f88dc96acf9e971908c1badf3305ee618ca1.tar.gz mailman-4b77f88dc96acf9e971908c1badf3305ee618ca1.tar.zst mailman-4b77f88dc96acf9e971908c1badf3305ee618ca1.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/alias-wrapper.c | 45 | ||||
| -rw-r--r-- | src/cgi-wrapper.c | 134 | ||||
| -rw-r--r-- | src/common.c | 171 | ||||
| -rw-r--r-- | src/common.h | 31 | ||||
| -rw-r--r-- | src/mail-wrapper.c | 174 |
5 files changed, 323 insertions, 232 deletions
diff --git a/src/alias-wrapper.c b/src/alias-wrapper.c index 0b0132246..7930b7ca3 100644 --- a/src/alias-wrapper.c +++ b/src/alias-wrapper.c @@ -1,29 +1,28 @@ -/* -** alias-wrapper.c: -** wrapper to allow the mailman user to modify the aliases database. -** -** Copyright (C) 1998 by the Free Software Foundation, Inc. -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ +/* alias-wrapper.c --- wrapper to allow the mailman user to modify the aliases + * database. + * + * Copyright (C) 1998 by the Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #include <stdio.h> - -const int LEGAL_PARENT_UID = 9001; /* mailman's UID */ -const int LEGAL_PARENT_GID = 6; /* mailman's GID */ +/* passed in from configure script */ +const int LEGAL_PARENT_UID = ALIAS_UID; /* mailman's UID */ +const int LEGAL_PARENT_GID = ALIAS_GID; /* mail's GID */ const char* SENDMAIL_CMD = "/usr/sbin/sendmail"; const char* ALIAS_FILE = "/etc/aliases"; diff --git a/src/cgi-wrapper.c b/src/cgi-wrapper.c index 37226adcb..6d45e4004 100644 --- a/src/cgi-wrapper.c +++ b/src/cgi-wrapper.c @@ -1,105 +1,53 @@ -/* -** cgi-wrapper.c: -** generic wrapper that will take info from a environment -** variable, and pass it to two commands. -** -** Copyright (C) 1998 by the Free Software Foundation, Inc. -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** 10-17-96 : Hal Schechner (hal-j@channel21.com) -** -** 12-14-96 : John Viega (viega@list.org) -** changed to work on 1 command, take a list of -** valid commands, just pass on argv, and use -** execvp() Also threw in some useful feedback for -** when there's a failure, mainly for future -** debugging. -** -** 03-31-98 : John Viega (viega@list.org) -** Consolidated all CGI wrappers into 1, removed -** checking the command name, (it was not real -** security anyway...) and changed it to use -** syslog on error. This definitely doesn't have -** any of Hal's code left ;-) -** -*/ - -#include <stdio.h> -#include <stdarg.h> -#include <syslog.h> - -#define COMMAND "/home/mailman/mailman/cgi/" ## SCRIPT -#define LOG_IDENT "Mailman-wrapper (" ## SCRIPT ## ")" - -const int LEGAL_PARENT_UID = 60001; /* nobody's UID */ -const int LEGAL_PARENT_GID = 60001; /* nobody's GID */ +/* cgi-wrapper.c --- Generic wrapper that will take info from a environment + * variable, and pass it to two commands. + * + * Copyright (C) 1998 by the Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ -/* -** Report an error then exit. -*/ -void -err(char *format, ...) -{ - char log_entry[1024]; +#include "common.h" - va_list arg_ptr; - va_start(arg_ptr, format); - vsprintf(log_entry, format, arg_ptr); - va_end(arg_ptr); +/* passed in by configure */ +#define SCRIPTNAME SCRIPT +#define LOG_IDENT "Mailman cgi-wrapper (" ## SCRIPT ## ")" +#define LEGAL_PARENT_UID CGI_UID /* nobody's UID */ +#define LEGAL_PARENT_GID CGI_GID /* nobody's GID */ - /* Write to the console, maillog is often mostly ignored, and root - * should definitely know about any problems. - */ - openlog(LOG_IDENT, LOG_CONS, LOG_MAIL); - syslog(LOG_ERR, "%s", log_entry); - closelog(); - exit(0); -} +const char* logident = LOG_IDENT; +const char* script = SCRIPTNAME; +const int parentuid = LEGAL_PARENT_UID; +const int parentgid = LEGAL_PARENT_GID; -/* -** is the parent process allowed to call us? -*/ -void -check_caller() +int +main(int argc, char** argv, char** env) { - /* compare to our parent's uid */ - if (LEGAL_PARENT_UID != getuid()) { - err("Attempt to exec cgi %d made by uid %d", - LEGAL_PARENT_UID, - getuid()); - } - if (LEGAL_PARENT_GID != getgid()) { - err("Attempt to exec cgi %d made by gid %d", - LEGAL_PARENT_GID, - getgid()); - } -} + int status; + check_caller(logident, parentuid, parentgid); -int -main(int argc, char **argv, char **env) -{ - int i; + /* if we get here, the caller is OK */ + status = setuid(geteuid()); + if (status) + fatal(logident, "%s", strerror(errno)); - check_caller(); - /* If we get here, the caller is OK. */ - setuid(geteuid()); - execve(COMMAND, &argv[0], env); - err("execve of %s failed!", COMMAND); + status = run_script(script, argc, argv, env); + fatal(logident, "%s", strerror(errno)); + return status; } diff --git a/src/common.c b/src/common.c new file mode 100644 index 000000000..f21b49759 --- /dev/null +++ b/src/common.c @@ -0,0 +1,171 @@ +/* common.c --- Common routines, constants, etc. Used by all the wrappers. + * + * Copyright (C) 1998 by the Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "common.h" + +/* passed in by configure */ +#define SCRIPTDIR PREFIX ## "/scripts/" /* trailing slash */ +#define MODULEDIR PREFIX ## "/Mailman" /* no trailing slash */ + +const char* prefixdir = PREFIX; +const char* scriptdir = SCRIPTDIR; +const char* moduledir = MODULEDIR; +char* python = PYTHON; + + + +/* Report on errors and exit + */ +void +fatal(const char* ident, const char* format, ...) +{ + char log_entry[1024]; + + va_list arg_ptr; + va_start(arg_ptr, format); + vsprintf(log_entry, format, arg_ptr); + va_end(arg_ptr); + + /* Write to the console, maillog is often mostly ignored, and root + * should definitely know about any problems. + */ + openlog(ident, LOG_CONS, LOG_MAIL); + syslog(LOG_ERR, "%s", log_entry); + closelog(); + exit(1); +} + + + +/* Is the parent process allowed to call us? + */ +void +check_caller(const char* ident, uid_t parentuid, gid_t parentgid) +{ + /* compare to our parent's uid */ + if (parentuid != getuid()) { + fatal(ident, + "Attempt to exec script with invalid uid %d, expected %d", + getuid(), parentuid); + } + if (parentgid != getgid()) { + fatal(ident, + "Attempt to exec script with invalid gid %d, expected %d", + getgid(), parentgid); + } +} + + + +/* Run a Python script out of the script directory + * + * args[0] should be the abs path to the Python script to execute + * argv[1:] are other args for the script + * env may or may not contain PYTHONPATH, we'll substitute our own + */ +int +run_script(const char* script, int argc, char** argv, char** env) +{ + const char envstr[] = "PYTHONPATH="; + const int envlen = strlen(envstr); + + int envcnt = 0; + int i, j, status; + char** newenv; + char** newargv; + + /* We want to tightly control how the CGI scripts get executed. + * For portability and security, the path to the Python executable + * is hard-coded into this C wrapper, rather than encoded in the #! + * line of the script that gets executed. So we invoke those + * scripts by passing the script name on the command line to the + * Python executable. + * + * We also need to hack on the PYTHONPATH environment variable so + * that the path to the installed Mailman modules will show up + * first on sys.path. + * + */ + for (envcnt = 0; env[envcnt]; envcnt++) + ; + + /* okay to be a little too big */ + newenv = (char**)malloc(sizeof(char*) * (envcnt + 2)); + + /* filter out any existing PYTHONPATH in the environment */ + for (i = 0, j = 0; i < envcnt; i++) + if (strncmp(envstr, env[i], envlen)) { + newenv[i] = env[j]; + j++; + } + + /* Tack on our own version of PYTHONPATH, which should contain only + * the path to the Mailman package modules. + * + * $(PREFIX)/modules + */ + newenv[j] = (char*)malloc(sizeof(char) * ( + strlen(envstr) + + strlen(moduledir) + + 1)); + strcpy(newenv[j], envstr); + strcat(newenv[j], moduledir); + j++; + + newenv[j] = NULL; + + /* Now put together argv. This will contain first the absolute path + * to the python executable, then the absolute path to the script, + * then any additional args passed in argv above. + */ + newargv = (char**)malloc(sizeof(char*) * (argc + 2)); + newargv[0] = python; + newargv[1] = (char*)malloc(sizeof(char) * ( + strlen(scriptdir) + + strlen(script) + + 1)); + strcpy(newargv[1], scriptdir); + strcat(newargv[1], script); + + /* now tack on all the rest of the arguments. we can skip argv's + * first two arguments because, for cgi-wrapper there is only argv[0]. + * For mail-wrapper, argv[1] is the mail command (e.g. post, + * mailowner, or mailcmd) and argv[2] is the listname. The mail + * command to execute gets passed in as this function's `script' + * parameter and becomes the argument to the python interpreter. The + * list name therefore should become argv[2] to this process. + * + * TBD: have to make sure this works with alias-wrapper. + */ + for (i = 2; i < argc; i++) + newargv[i] = argv[i]; + + newargv[i] = NULL; + + status = execve(python, &newargv[0], &newenv[0]); + return status; +} + + + +/* + * Local Variables: + * c-file-style: "python" + * End: + */ diff --git a/src/common.h b/src/common.h new file mode 100644 index 000000000..a72a4c258 --- /dev/null +++ b/src/common.h @@ -0,0 +1,31 @@ +/* common.h --- Prototypes for common routines + * + * Copyright (C) 1998 by the Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdlib.h> +#include <stdarg.h> +#include <syslog.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> + +void fatal(const char*, const char*, ...); +void check_caller(const char*, uid_t, gid_t); +int run_script(const char*, int, char**, char**); diff --git a/src/mail-wrapper.c b/src/mail-wrapper.c index ea15c409c..1c5390ee9 100644 --- a/src/mail-wrapper.c +++ b/src/mail-wrapper.c @@ -1,49 +1,40 @@ -/* -** mail-wrapper.c: -** generic wrapper that will take info from a environment -** variable, and pass it to two commands. -** -** Copyright (C) 1998 by the Free Software Foundation, Inc. -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** 10-17-96 : Hal Schechner (hal-j@channel21.com) -** -** 12-14-96 : John Viega (viega@list.org) -** changed to work on 1 command, take a list of -** valid commands, just pass on argv, and use -** execvp() Also threw in some useful feedback for -** when there's a failure, mainly for future -** debugging. Made it a root script so we could -** call setuid() -** -** Chmod this 4755. -** -*/ -#include <stdio.h> +/* mail-wrapper.c --- Generic wrapper that will take info from a environment + * variable, and pass it to two commands. + * + * Copyright (C) 1998 by the Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "common.h" -const char *COMMAND_LOCATION = "/home/mailman/mailman/scripts"; +/* TBD: Should make these arrays too?... */ +#define LEGAL_PARENT_UID MAIL_UID /* mail's UID */ +#define LEGAL_PARENT_GID MAIL_GID /* mail's GID */ -extern int errno; -FILE *f; +const int parentuid = LEGAL_PARENT_UID; +const int parentgid = LEGAL_PARENT_GID; +const char* logident = "Mailman mail-wrapper"; + + const char *VALID_COMMANDS[] = { "post", "mailcmd", "mailowner", - NULL /* Sentinal, don't remove */ + NULL /* Sentinel, don't remove */ }; @@ -52,115 +43,66 @@ const char *VALID_COMMANDS[] = { */ const char *LEGAL_PARENT_NAMES[] = { "sendmail", - NULL /* Sentinal, don't remove */ + NULL /* Sentinel, don't remove */ }; -/* Should make these arrays too... */ -const int LEGAL_PARENT_UID = 1; /* mail's UID */ -const int LEGAL_PARENT_GID = 1; /* mail's GID */ - - -/* -** what is the name of the process with pid of 'pid' -*/ -char * -get_process_name(int pid) -{ - FILE *proc; - char fname[30]; - char tmp[255]; - static char procname[255]; - - sprintf(fname, "/proc/%d/status", pid); - proc = fopen(fname, "r"); - fgets(tmp, 256, proc); - sscanf(tmp, "Name: %s\n", procname); - fclose(proc); - return procname; -} - + int -valid_parent(char *parent) +check_parent(char *parent) { int i = 0; - while (LEGAL_PARENT_NAMES[i] != NULL) { - if (!strcmp(parent, LEGAL_PARENT_NAMES[i])) { + while (LEGAL_PARENT_NAMES[i]) { + if (!strcmp(parent, LEGAL_PARENT_NAMES[i])) return 1; - } i++; } return 0; } -/* -** is the parent process allowed to call us? -*/ -int -legal_caller() -{ - /* compare to our parent's uid */ - if (LEGAL_PARENT_UID != getuid()) { - /* fprintf(f,"GOT UID %d.\n", getuid()); */ - printf("GOT UID %d.\n", getuid()); - return 0; - } - if (LEGAL_PARENT_GID != getgid()) { - /* fprintf(f,"GOT GID %d.\n", getgid()); */ - printf("GOT GID %d.\n", getgid()); - return 0; - } - return 1; -} - - int -valid_command(char *command) +check_command(char *command) { int i = 0; while (VALID_COMMANDS[i] != NULL) { - if (!strcmp(command, VALID_COMMANDS[i])) { + if (!strcmp(command, VALID_COMMANDS[i])) return 1; - } i++; } return 0; } + int -main(int argc, char **argv) +main(int argc, char** argv, char** env) { - char *command; - int i; - - if (argc < 2) { - printf("Usage: %s program [args...]\n", argv[0]); - fflush(stdout); - exit(0); - } - i = strlen(argv[1]) + strlen(COMMAND_LOCATION) + 2; - command = (char *)malloc(sizeof(char) * i); - sprintf(command, "%s/%s", COMMAND_LOCATION, argv[1]); + int status; - if (!valid_command(argv[1])) { - printf("Illegal command.\n"); - } - else { - if (legal_caller()) { - setuid(geteuid()); - execv(command, &argv[1]); - } - else { - printf("Illegal caller!\n"); - } - } + /* sanity check arguments */ + if (argc < 2) + fatal(logident, "Usage: %s program [args...]\n", argv[0]); + + if (!check_command(argv[1])) + fatal(logident, "Illegal command: %s", argv[1]); + + check_caller(logident, parentuid, parentgid); + + /* If we got here, everything must be OK */ + status = setuid(geteuid()); + if (status) + fatal(logident, "%s", strerror(errno)); + + status = run_script(argv[1], argc, argv, env); + fatal(logident, "%s", strerror(errno)); + return status; } + /* * Local Variables: |
