]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20011128
authorWietse Venema <wietse@porcupine.org>
Wed, 28 Nov 2001 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:27:39 +0000 (06:27 +0000)
postfix/HISTORY
postfix/html/smtpd.8.html
postfix/man/man8/smtpd.8
postfix/src/global/Makefile.in
postfix/src/global/mail_stream.c
postfix/src/global/mail_version.h
postfix/src/global/recdump.c
postfix/src/postdrop/Makefile.in
postfix/src/postdrop/postdrop.c
postfix/src/sendmail/sendmail.c
postfix/src/trivial-rewrite/Makefile.in

index 73768300a066032d6da94fa4e63f60beeae1d33d..7a863fecfacb085d6f27888d24193d6ac3d9b465 100644 (file)
@@ -5720,6 +5720,20 @@ Apologies for any names omitted.
        Parameter: fault_injection_code, must be left at zero for
        production use.
 
+20011128
+
+       Robustness: add a file size limit to the sendmail and
+       postdrop submission programs to stop run-away process
+       accidents. This is not a defense against DOS attack.
+       Files: sendmail/sendmail.c, postdrop/postdrop.c.
+
+       That resulted in a considerable amount of work to properly
+       propagate "file too large" conditions back to the sendmail
+       mail posting user interface. Took the opportunity to express
+       other mail submission fatal exits with the <sysexits.h>
+       exit status codes.  Files: sendmail/sendmail.c,
+       postdrop/postdrop.c.
+
 Open problems:
 
        Medium: need in-process caching for map lookups. LDAP
index 96fa20b5fa5162e6f00d719dd3aee1e485cb44c0..2d63496706ccb4aee3468deb8d03ca27c645ed5c 100644 (file)
@@ -77,9 +77,9 @@ SMTPD(8)                                                 SMTPD(8)
 
        <b>smtpd</b><i>_</i><b>noop</b><i>_</i><b>commands</b>
               List of commands that are treated as NOOP (no oper-
-              ation) commands without any parameter syntax check-
-              ing. This list overrides built-in  command  defini-
-              tions.
+              ation)   commands,  without  any  parameter  syntax
+              checking and without any state change.   This  list
+              overrides built-in command definitions.
 
 <b>Authentication</b> <b>controls</b>
        <b>enable</b><i>_</i><b>sasl</b><i>_</i><b>authentication</b>
index 257d12554759a5f5c4b8e857bde1624393c719bd..aea27968dff19baf4f3d73b1ea34610c3ba33d25 100644 (file)
@@ -83,9 +83,9 @@ either bounces mail or re-injects the result back into Postfix.
 This parameter uses the same syntax as the right-hand side of
 a Postfix transport table.
 .IP \fBsmtpd_noop_commands\fR
-List of commands that are treated as NOOP (no operation) commands
-without any parameter syntax checking. This list overrides built-in
-command definitions.
+List of commands that are treated as NOOP (no operation) commands,
+without any parameter syntax checking and without any state change.
+This list overrides built-in command definitions.
 .SH "Authentication controls"
 .IP \fBenable_sasl_authentication\fR
 Enable per-session authentication as per RFC 2554 (SASL).
index 6ce1247a6aa5064b09aabd155547e9340b4f90c5..33f7f37229d7ae47c6b833554f08f2712a73ffd1 100644 (file)
@@ -582,8 +582,9 @@ mail_copy.o: record.h
 mail_copy.o: rec_type.h
 mail_copy.o: mail_queue.h
 mail_copy.o: mail_addr.h
-mail_copy.o: mail_copy.h
 mail_copy.o: mark_corrupt.h
+mail_copy.o: mail_params.h
+mail_copy.o: mail_copy.h
 mail_date.o: mail_date.c
 mail_date.o: ../../include/sys_defs.h
 mail_date.o: ../../include/msg.h
index ed58493da5c1bd801af9dab158bfd61bd7953837..ac5e232a28df8aca68b3321145edb8c685c18b55 100644 (file)
@@ -80,6 +80,7 @@
 #include <sys_defs.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <errno.h>
 
 /* Utility library. */
 
@@ -141,7 +142,7 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
        || fsync(vstream_fileno(info->stream))
 #endif
        )
-       status = CLEANUP_STAT_WRITE;
+       status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
 
     /*
      * Close the queue file and mark it as closed. Be prepared for
@@ -152,7 +153,7 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
      * reasons.
      */
     if (info->close(info->stream))
-       status = CLEANUP_STAT_WRITE;
+       status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
     info->stream = 0;
 
     /*
index 928f94824c5f586b4a2bd18e7a61dc96c9a75f17..8e34f486bbb6a59506346cb0b4d272b5cfbb211d 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20011127"
+#define DEF_MAIL_VERSION       "Snapshot-20011128"
 extern char *var_mail_version;
 
 /* LICENSE
index a02d1755e5dcb3d54c0fc0a5ca9e214f8ab9e4d2..74ff7ea02e0270cb028ee5adbb216b971e0ad389 100644 (file)
@@ -44,7 +44,8 @@ int     main(int unused_argc, char **argv)
     msg_vstream_init(argv[0], VSTREAM_OUT);
 
     while (offset = vstream_ftell(VSTREAM_IN),
-          (type = rec_get(VSTREAM_IN, buf, 0)) > 0) {
+          ((type = rec_get(VSTREAM_IN, buf, 0)) != REC_TYPE_EOF
+          && type != REC_TYPE_ERROR)) {
        vstream_fprintf(VSTREAM_OUT, "%15s|%4ld|%3d|%s\n",
                        rec_type_name(type), offset,
                        VSTRING_LEN(buf), vstring_str(buf));
index 249fac4348b333742c76195897c65d9e7fa7f321..a58a1b581ce93eba27406c5b1240bb7acb748cb3 100644 (file)
@@ -63,8 +63,8 @@ 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
index 928f46c41f100e84d5f13a10b7e7f79228db9a42..51f95cfdbab28e41ff975231d0ea5794665aa752 100644 (file)
@@ -75,6 +75,7 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <syslog.h>
+#include <errno.h>
 
 /* Utility library. */
 
@@ -85,6 +86,7 @@
 #include <msg_vstream.h>
 #include <msg_syslog.h>
 #include <argv.h>
+#include <iostuff.h>
 
 /* Global library. */
 
@@ -197,6 +199,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 (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.
      */
@@ -214,6 +223,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);
@@ -254,6 +264,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);
@@ -279,8 +292,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;
     }
@@ -289,8 +306,10 @@ int     main(int argc, char **argv)
     /*
      * Finish the file.
      */
-    if ((status = mail_stream_finish(dst, (VSTRING *) 0)) != 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
index 86de7ec27a54ac28822a59402211efbb6713fbc6..a5039e8a80a3995f0179c2f2b5fc246e70a5054b 100644 (file)
 /*     configuration parameter instead.
 /* .IP \fB-qR\fIsite\fR
 /*     Schedule immediate delivery of all mail that is queued for the named
-/*     \fIsite\fR. This option accepts only \fIsite\fR names that are 
+/*     \fIsite\fR. This option accepts only \fIsite\fR names that are
 /*     eligible for the "fast flush" service, and is implemented by
 /*     connecting to the local SMTP server at \fB$myhostname\fR.
 /*     See \fBflush\fR(8) for more information about the "fast flush"
 #include <errno.h>
 #include <ctype.h>
 #include <stdarg.h>
+#include <sysexits.h>
 
 /* Utility library. */
 
   */
 static char *sendmail_path;
 static void sendmail_cleanup(void);
+static NORETURN fatal_error(int, const char *,...);
 
  /*
   * Flag parade.
@@ -492,8 +494,8 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
        if ((flags & SM_FLAG_AEOF) && VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
            break;
        if (REC_PUT_BUF(dst, type, buf) < 0)
-           msg_fatal("%s(%ld): error writing queue file: %m",
-                     saved_sender, (long) uid);
+           fatal_error(EX_CANTCREAT, "%s(%ld): error writing queue file: %m",
+                       saved_sender, (long) uid);
     }
 
     /*
@@ -514,11 +516,11 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
      * handler from removing the file.
      */
     if (vstream_ferror(VSTREAM_IN))
-       msg_fatal("%s(%ld): error reading input: %m",
-                 saved_sender, (long) uid);
+       fatal_error(EX_DATAERR, "%s(%ld): error reading input: %m",
+                   saved_sender, (long) uid);
     if ((status = mail_stream_finish(handle, (VSTRING *) 0)) != 0)
-       msg_fatal("%s(%ld): %s", saved_sender,
-                 (long) uid, cleanup_strerror(status));
+       fatal_error(EX_CANTCREAT, "%s(%ld): %s", saved_sender,
+                   (long) uid, cleanup_strerror(status));
     if (sendmail_path) {
        myfree(sendmail_path);
        sendmail_path = 0;
@@ -667,9 +669,11 @@ static void flush_site(const char *site)
     vstring_free(buf);
 }
 
+static int fatal_status;
+
 /* sendmail_cleanup - callback for the runtime error handler */
 
-static void sendmail_cleanup(void)
+static NORETURN sendmail_cleanup(void)
 {
 
     /*
@@ -684,14 +688,29 @@ static void sendmail_cleanup(void)
            msg_info("remove %s", sendmail_path);
        sendmail_path = 0;
     }
+    exit(fatal_status > 0 ? fatal_status : 1);
 }
 
 /* sendmail_sig - catch signal and clean up */
 
 static void sendmail_sig(int sig)
 {
+    fatal_status = sig;
     sendmail_cleanup();
-    exit(sig);
+}
+
+/* fatal_error - give up and notify parent */
+
+static void fatal_error(int status, const char *fmt,...)
+{
+    VSTRING *text = vstring_alloc(10);
+    va_list ap;
+
+    fatal_status = status;
+    va_start(ap, fmt);
+    vstring_vsprintf(text, fmt, ap);
+    va_end(ap);
+    msg_fatal("%s", vstring_str(text));
 }
 
 /* main - the main program */
@@ -726,7 +745,7 @@ int     main(int argc, char **argv)
     for (fd = 0; fd < 3; fd++)
        if (fstat(fd, &st) == -1
            && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
-           msg_fatal("open /dev/null: %m");
+           fatal_error(EX_UNAVAILABLE, "open /dev/null: %m");
 
     /*
      * The CDE desktop calendar manager leaks a parent file descriptor into
@@ -774,9 +793,17 @@ int     main(int argc, char **argv)
      */
     mail_conf_read();
     if (chdir(var_queue_dir))
-       msg_fatal("chdir %s: %m", var_queue_dir);
+       fatal_error(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
+
+    /*
+     * Stop run-away process accidents by limiting the queue file size. This
+     * is not a defense against DOS attack.
+     */
+    if (get_file_limit() > var_message_limit)
+       set_file_limit((off_t) var_message_limit);
 
     signal(SIGPIPE, SIG_IGN);
+    signal(SIGXFSZ, SIG_IGN);
 
     signal(SIGHUP, sendmail_sig);
     signal(SIGINT, sendmail_sig);
@@ -836,7 +863,7 @@ int     main(int argc, char **argv)
                msg_info("-%c option ignored", c);
            break;
        case 'n':
-           msg_fatal("-%c option not supported", c);
+           fatal_error(EX_USAGE, "-%c option not supported", c);
        case 'B':                               /* body type */
            break;
        case 'F':                               /* full name */
@@ -853,14 +880,14 @@ int     main(int argc, char **argv)
            break;
        case 'V':                               /* VERP */
            if (verp_delims_verify(optarg) != 0)
-               msg_fatal("-V option requires two characters from %s",
-                         var_verp_filter);
+               fatal_error(EX_USAGE, "-V requires two characters from %s",
+                           var_verp_filter);
            verp_delims = optarg;
            break;
        case 'b':
            switch (*optarg) {
            default:
-               msg_fatal("unsupported: -%c%c", c, *optarg);
+               fatal_error(EX_USAGE, "unsupported: -%c%c", c, *optarg);
            case 'd':                           /* daemon mode */
                if (mode == SM_MODE_FLUSHQ)
                    msg_warn("ignoring -q option in daemon mode");
@@ -894,7 +921,7 @@ int     main(int argc, char **argv)
                break;
            case 'A':
                if (optarg[1] == 0)
-                   msg_fatal("-oA requires pathname");
+                   fatal_error(EX_USAGE, "-oA requires pathname");
                myfree(var_alias_db_map);
                var_alias_db_map = mystrdup(optarg + 1);
                set_mail_conf_str(VAR_ALIAS_DB_MAP, var_alias_db_map);
@@ -924,7 +951,7 @@ int     main(int argc, char **argv)
                if (*site_to_flush == 0)
                    msg_fatal("specify: -qRsitename");
            } else {
-               msg_fatal("-q%c is not implemented", optarg[0]);
+               fatal_error(EX_USAGE, "-q%c is not implemented", optarg[0]);
            }
            break;
        case 't':
@@ -934,7 +961,7 @@ int     main(int argc, char **argv)
            msg_verbose++;
            break;
        case '?':
-           msg_fatal("usage: %s [options]", argv[0]);
+           fatal_error(EX_USAGE, "usage: %s [options]", argv[0]);
        }
     }
 
index 8890cdadc7fff77d92ec37d33315d15bfd486889..7f33c4c376f318bbe9b512fa8ddff79692e5d362 100644 (file)
@@ -110,6 +110,8 @@ transport.o: ../../include/vstream.h
 transport.o: ../../include/argv.h
 transport.o: ../../include/mail_params.h
 transport.o: ../../include/maps.h
+transport.o: ../../include/match_parent_style.h
+transport.o: ../../include/match_ops.h
 transport.o: transport.h
 trivial-rewrite.o: trivial-rewrite.c
 trivial-rewrite.o: ../../include/sys_defs.h