summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbwarsaw1998-05-26 18:42:44 +0000
committerbwarsaw1998-05-26 18:42:44 +0000
commit4b77f88dc96acf9e971908c1badf3305ee618ca1 (patch)
treec425088f9db12fb3f826136f167be5cdc77a9bb4 /src
parenta38041fa64fb30b661a9a55a6c9a3c313ba453a4 (diff)
downloadmailman-4b77f88dc96acf9e971908c1badf3305ee618ca1.tar.gz
mailman-4b77f88dc96acf9e971908c1badf3305ee618ca1.tar.zst
mailman-4b77f88dc96acf9e971908c1badf3305ee618ca1.zip
Diffstat (limited to 'src')
-rw-r--r--src/alias-wrapper.c45
-rw-r--r--src/cgi-wrapper.c134
-rw-r--r--src/common.c171
-rw-r--r--src/common.h31
-rw-r--r--src/mail-wrapper.c174
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: