diff options
| author | perry <perry@NetBSD.org> | 2002-02-02 23:10:24 +0000 |
|---|---|---|
| committer | perry <perry@NetBSD.org> | 2002-02-02 23:10:24 +0000 |
| commit | 6f59dc7aebbf705da79e61ef3fd24b48ed99d327 (patch) | |
| tree | c6e9fd356c8aac78b966a9dd53f5d0d14d5e62cd /gnu/dist/postfix/src/postdrop | |
| parent | ecf43984517b4cfb837e78958769cc8207ea5288 (diff) | |
Postfix 1.1.2
(Postfix releases are now numbered -- 1.1.2 means 1.1, patchlevel 2.)
Lots of new features, same great security.
Diffstat (limited to 'gnu/dist/postfix/src/postdrop')
| -rw-r--r-- | gnu/dist/postfix/src/postdrop/Makefile.in | 3 | ||||
| -rw-r--r-- | gnu/dist/postfix/src/postdrop/postdrop.c | 134 |
2 files changed, 98 insertions, 39 deletions
diff --git a/gnu/dist/postfix/src/postdrop/Makefile.in b/gnu/dist/postfix/src/postdrop/Makefile.in index 2d893c3ac61..a58a1b581ce 100644 --- a/gnu/dist/postfix/src/postdrop/Makefile.in +++ b/gnu/dist/postfix/src/postdrop/Makefile.in @@ -63,8 +63,9 @@ postdrop.o: ../../include/vstring.h postdrop.o: ../../include/msg_vstream.h postdrop.o: ../../include/msg_syslog.h postdrop.o: ../../include/argv.h -postdrop.o: ../../include/mail_proto.h postdrop.o: ../../include/iostuff.h +postdrop.o: ../../include/mail_proto.h +postdrop.o: ../../include/attr.h postdrop.o: ../../include/mail_queue.h postdrop.o: ../../include/mail_params.h postdrop.o: ../../include/mail_conf.h diff --git a/gnu/dist/postfix/src/postdrop/postdrop.c b/gnu/dist/postfix/src/postdrop/postdrop.c index 4a8c16d3c48..dacd70fdee5 100644 --- a/gnu/dist/postfix/src/postdrop/postdrop.c +++ b/gnu/dist/postfix/src/postdrop/postdrop.c @@ -2,29 +2,31 @@ /* NAME /* postdrop 1 /* SUMMARY -/* Postfix mail posting agent +/* Postfix mail posting utility /* SYNOPSIS -/* \fBpostdrop\fR [\fIoption ...\fR] +/* \fBpostdrop\fR [\fB-rv\fR] [\fB-c \fIconfig_dir\fR] /* DESCRIPTION /* The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR /* directory and copies its standard input to the file. /* -/* The command is designed to run with set-gid privileges, and with -/* group write permission to the \fBmaildrop\fR queue directory. -/* -/* The \fBpostdrop\fR command is automatically invoked by the -/* \fBsendmail\fR(1) mail posting agent when the \fBmaildrop\fR -/* queue directory is not world-writable. -/* /* Options: +/* .IP \fB-c \fIconfig_dir\fR +/* The \fBmain.cf\fR configuration file is in the named directory +/* instead of the default configuration directory. See also the +/* MAIL_CONFIG environment setting below. +/* .IP \fB-r\fR +/* Use a Postfix-internal protocol for reading the message from +/* standard input, and for reporting status information on standard +/* output. This is currently the only supported method. /* .IP \fB-v\fR /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR /* options make the software increasingly verbose. /* SECURITY /* .ad /* .fi -/* This program is designed so that it can run with set-user (or -/* group) id privileges. +/* The command is designed to run with set-group ID privileges, so +/* that it can write to the \fBmaildrop\fR queue directory and so that +/* it can connect to Postfix daemon processes. /* DIAGNOSTICS /* Fatal errors: malformed input, I/O error, out of memory. Problems /* are logged to \fBsyslogd\fR(8) and to the standard error stream. @@ -33,8 +35,16 @@ /* ENVIRONMENT /* .ad /* .fi -/* The program deletes all environment information, because the C -/* library can't be trusted. +/* .IP MAIL_CONFIG +/* Directory with the \fBmain.cf\fR file. In order to avoid exploitation +/* of set-group ID privileges, it is not possible to specify arbitrary +/* directory names. +/* +/* A non-standard directory is allowed only if the name is listed in the +/* standard \fBmain.cf\fR file, in the \fBalternate_config_directories\fR +/* configuration parameter value. +/* +/* Only the super-user is allowed to specify arbitrary directory names. /* FILES /* /var/spool/postfix, mail queue /* /etc/postfix, configuration files @@ -75,6 +85,7 @@ #include <stdlib.h> #include <signal.h> #include <syslog.h> +#include <errno.h> /* Utility library. */ @@ -85,6 +96,7 @@ #include <msg_vstream.h> #include <msg_syslog.h> #include <argv.h> +#include <iostuff.h> /* Global library. */ @@ -104,10 +116,14 @@ /* * WARNING WARNING WARNING * - * This software is designed to run set-gid on systems that cannot afford a - * world-writable spool directory. In order to make this restriction work, - * this software should not run any external commands, nor should it take - * any configuration information from the user. + * This software is designed to run set-gid. In order to avoid exploitation of + * privilege, this software should not run any external commands, nor should + * it take any information from the user unless that information can be + * properly sanitized. To get an idea of how much information a process can + * inherit from a potentially hostile user, examine all the members of the + * process structure (typically, in /usr/include/sys/proc.h): the current + * directory, open files, timers, signals, environment, command line, umask, + * and so on. */ /* @@ -137,8 +153,17 @@ static void postdrop_cleanup(void) static void postdrop_sig(int sig) { - postdrop_cleanup(); - exit(sig); + + /* + * Assume atomic signal() updates, even when emulated with sigaction(). + */ + if (signal(SIGHUP, SIG_IGN) != SIG_IGN + && signal(SIGINT, SIG_IGN) != SIG_IGN + && signal(SIGQUIT, SIG_IGN) != SIG_IGN + && signal(SIGTERM, SIG_IGN) != SIG_IGN) { + postdrop_cleanup(); + exit(sig); + } } /* main - the main program */ @@ -183,6 +208,28 @@ int main(int argc, char **argv) set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* + * Parse JCL. This program is set-gid and must sanitize all command-line + * arguments. The configuration directory argument is validated by the + * mail configuration read routine. Don't do complex things until we have + * completed initializations. + */ + while ((c = GETOPT(argc, argv, "c:rv")) > 0) { + switch (c) { + case 'c': + if (setenv(CONF_ENV_PATH, optarg, 1) < 0) + msg_fatal("out of memory"); + break; + case 'r': /* forward compatibility */ + break; + case 'v': + msg_verbose++; + break; + default: + msg_fatal("usage: %s [-c config_dir] [-v]", argv[0]); + } + } + + /* * Read the global configuration file and extract configuration * information. Some claim that the user should supply the working * directory instead. That might be OK, given that this command needs @@ -194,6 +241,13 @@ int main(int argc, char **argv) mail_conf_read(); /* + * Stop run-away process accidents by limiting the queue file size. This + * is not a defense against DOS attack. + */ + if (var_message_limit > 0 && get_file_limit() > var_message_limit) + set_file_limit((off_t) var_message_limit); + + /* * Strip the environment so we don't have to trust the C library. */ import_env = argv_split(var_import_environ, ", \t\r\n"); @@ -210,6 +264,7 @@ int main(int argc, char **argv) * clean up incomplete output. */ signal(SIGPIPE, SIG_IGN); + signal(SIGXFSZ, SIG_IGN); signal(SIGHUP, postdrop_sig); signal(SIGINT, postdrop_sig); @@ -217,18 +272,7 @@ int main(int argc, char **argv) signal(SIGTERM, postdrop_sig); msg_cleanup(postdrop_cleanup); - /* - * Parse JCL. - */ - while ((c = GETOPT(argc, argv, "v")) > 0) { - switch (c) { - case 'v': - msg_verbose++; - break; - default: - msg_fatal("usage: %s [-v]", argv[0]); - } - } + /* End of initializations. */ /* * Create queue file. mail_stream_file() never fails. Send the queue ID @@ -236,8 +280,10 @@ int main(int argc, char **argv) * clean up in case of a fatal error or an interrupt. */ dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC, - MAIL_SERVICE_PICKUP); - mail_print(VSTREAM_OUT, "%s", dst->id); + MAIL_SERVICE_PICKUP, 0444); + attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, + ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, dst->id, + ATTR_TYPE_END); vstream_fflush(VSTREAM_OUT); postdrop_path = mystrdup(VSTREAM_PATH(dst->stream)); @@ -248,6 +294,9 @@ int main(int argc, char **argv) * file descriptor to the cleanup daemon. These are by no means all * sanity checks - the cleanup service and queue manager services will * reject messages that lack required information. + * + * If something goes wrong, slurp up the input before responding to the + * client, otherwise the client will give up after detecting SIGPIPE. */ vstream_control(VSTREAM_IN, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END); buf = vstring_alloc(100); @@ -273,8 +322,12 @@ int main(int argc, char **argv) msg_fatal("uid=%ld: unexpected record type: %d", (long) uid, rec_type); if (rec_type == **expected) expected++; - if (REC_PUT_BUF(dst->stream, rec_type, buf) < 0) - msg_fatal("uid=%ld: queue file write error", (long) uid); + if (REC_PUT_BUF(dst->stream, rec_type, buf) < 0) { + while ((rec_type = rec_get(VSTREAM_IN, buf, var_line_limit)) > 0 + && rec_type != REC_TYPE_END) + /* void */ ; + break; + } if (rec_type == REC_TYPE_END) break; } @@ -283,8 +336,10 @@ int main(int argc, char **argv) /* * Finish the file. */ - if ((status = mail_stream_finish(dst)) != 0) - msg_fatal("uid=%ld: %s", (long) uid, cleanup_strerror(status)); + if ((status = mail_stream_finish(dst, (VSTRING *) 0)) != 0) { + postdrop_cleanup(); + msg_warn("uid=%ld: %m", (long) uid); + } /* * Disable deletion on fatal error before reporting success, so the file @@ -298,7 +353,10 @@ int main(int argc, char **argv) /* * Send the completion status to the caller and terminate. */ - mail_print(VSTREAM_OUT, "%d", status); + attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_STR, MAIL_ATTR_WHY, "", + ATTR_TYPE_END); vstream_fflush(VSTREAM_OUT); exit(status); } |
