summaryrefslogtreecommitdiff
path: root/gnu/dist/postfix/src/postdrop
diff options
context:
space:
mode:
authorperry <perry@NetBSD.org>2002-02-02 23:10:24 +0000
committerperry <perry@NetBSD.org>2002-02-02 23:10:24 +0000
commit6f59dc7aebbf705da79e61ef3fd24b48ed99d327 (patch)
treec6e9fd356c8aac78b966a9dd53f5d0d14d5e62cd /gnu/dist/postfix/src/postdrop
parentecf43984517b4cfb837e78958769cc8207ea5288 (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.in3
-rw-r--r--gnu/dist/postfix/src/postdrop/postdrop.c134
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);
}