From: Wietse Venema Date: Wed, 28 Nov 2001 05:00:00 +0000 (-0500) Subject: snapshot-20011128 X-Git-Tag: v1.1.0~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c740cf61fb3a081539c277aa49177ffd857f8e26;p=thirdparty%2Fpostfix.git snapshot-20011128 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 73768300a..7a863fecf 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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 + exit status codes. Files: sendmail/sendmail.c, + postdrop/postdrop.c. + Open problems: Medium: need in-process caching for map lookups. LDAP diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 96fa20b5f..2d6349670 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -77,9 +77,9 @@ SMTPD(8) SMTPD(8) smtpd_noop_commands 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. Authentication controls enable_sasl_authentication diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 257d12554..aea27968d 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -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). diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 6ce1247a6..33f7f3722 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -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 diff --git a/postfix/src/global/mail_stream.c b/postfix/src/global/mail_stream.c index ed58493da..ac5e232a2 100644 --- a/postfix/src/global/mail_stream.c +++ b/postfix/src/global/mail_stream.c @@ -80,6 +80,7 @@ #include #include #include +#include /* 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; /* diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 928f94824..8e34f486b 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 diff --git a/postfix/src/global/recdump.c b/postfix/src/global/recdump.c index a02d1755e..74ff7ea02 100644 --- a/postfix/src/global/recdump.c +++ b/postfix/src/global/recdump.c @@ -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)); diff --git a/postfix/src/postdrop/Makefile.in b/postfix/src/postdrop/Makefile.in index 249fac434..a58a1b581 100644 --- a/postfix/src/postdrop/Makefile.in +++ b/postfix/src/postdrop/Makefile.in @@ -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 diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 928f46c41..51f95cfdb 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -75,6 +75,7 @@ #include #include #include +#include /* Utility library. */ @@ -85,6 +86,7 @@ #include #include #include +#include /* 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 diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 86de7ec27..a5039e8a8 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -148,7 +148,7 @@ /* 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" @@ -276,6 +276,7 @@ #include #include #include +#include /* Utility library. */ @@ -331,6 +332,7 @@ */ 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]); } } diff --git a/postfix/src/trivial-rewrite/Makefile.in b/postfix/src/trivial-rewrite/Makefile.in index 8890cdadc..7f33c4c37 100644 --- a/postfix/src/trivial-rewrite/Makefile.in +++ b/postfix/src/trivial-rewrite/Makefile.in @@ -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