From: Wietse Venema Date: Fri, 25 Aug 2006 05:00:00 +0000 (-0500) Subject: postfix-2.4-20060825 X-Git-Tag: v2.4.0-RC1~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be48a120cf6cafb927023f5cb890f2d36c313845;p=thirdparty%2Fpostfix.git postfix-2.4-20060825 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 40cc32c29..5f0dc360a 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -12680,14 +12680,14 @@ Apologies for any names omitted. 20060823 - Bugfix (introduced Postfix 2.2): vstream_fdclose() did not - flush unwritten output before disconnecting a stream from - its file descriptor. File: util/vstream.c. - Bugfix (introduced Postfix 2.2): segfault when vstream_fclose() attempted to flush unwritten output, after vstream_fdclose() - disconnected the stream from its file descriptor. File: - util/vstream.c. + had already disconnected the stream from its file descriptor. + File: util/vstream.c. + + Bugfix (introduced Postfix 2.2): vstream_fdclose() did not + flush unwritten output before disconnecting a stream from + its file descriptor(s). File: util/vstream.c. Feature: smtp-sink can capture mail to file, either as one individual message per file, or as multiple messages per @@ -12708,6 +12708,17 @@ Apologies for any names omitted. Portability: inside functions, GCC 4 refuses forward declarations of static functions. File: smtpstone/smtp-sink.c. +20060825 + + Bugfix (introduced Postfix 2.3): with headers-only mail, a + Milter "header insert" action corrupted the queue file. The + cleanup server executed some end-of-body action before the + end-of-header actions. File: cleanup/cleanup_message.c. + + Robustness: mail delivery agents now detect loops in queue + files. Files with too many backward jumps are saved to the + "corrupt" directory. File: global/record.c. + Wish list: Make null local-part handling configurable: either expand diff --git a/postfix/html/smtp-sink.1.html b/postfix/html/smtp-sink.1.html index 04e44eac4..ec907ebdf 100644 --- a/postfix/html/smtp-sink.1.html +++ b/postfix/html/smtp-sink.1.html @@ -137,6 +137,11 @@ SMTP-SINK(1) SMTP-SINK(1) and use quotes to protect white space from the shell. Command names are case-insensitive. + -R root-directory + Change the process root directory to the specified + location. This option requires super-user privi- + leges. See also the -u option. + -s command,command,... Log the named commands to syslogd. @@ -160,6 +165,13 @@ SMTP-SINK(1) SMTP-SINK(1) Limit the time for receiving a command or sending a response. The time limit is specified in seconds. + -u username + Switch to the specified user privileges after open- + ing the network socket and optionally changing the + process root directory. This option is required + when the process runs with super-user privileges. + See also the -R option. + -v Show the SMTP conversations. -w delay diff --git a/postfix/man/man1/smtp-sink.1 b/postfix/man/man1/smtp-sink.1 index a1fc05a2d..c14515afd 100644 --- a/postfix/man/man1/smtp-sink.1 +++ b/postfix/man/man1/smtp-sink.1 @@ -119,6 +119,10 @@ Examples of commands are CONNECT, HELO, EHLO, LHLO, MAIL, RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT. Separate command names by white space or commas, and use quotes to protect white space from the shell. Command names are case-insensitive. +.IP "\fB-R \fIroot-directory\fR" +Change the process root directory to the specified location. +This option requires super-user privileges. See also the +\fB-u\fR option. .IP "\fB-s \fIcommand,command,...\fR" Log the named commands to syslogd. .sp @@ -137,6 +141,11 @@ character). .IP "\fB-t \fItimeout\fR (default: 100)" Limit the time for receiving a command or sending a response. The time limit is specified in seconds. +.IP "\fB-u \fIusername\fR" +Switch to the specified user privileges after opening the +network socket and optionally changing the process root +directory. This option is required when the process runs +with super-user privileges. See also the \fB-R\fR option. .IP \fB-v\fR Show the SMTP conversations. .IP "\fB-w \fIdelay\fR" diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index c990cdd7c..5af24c59c 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -797,10 +797,10 @@ static void cleanup_message_headerbody(CLEANUP_STATE *state, int type, * current file position so we can compute the message size lateron. */ else if (type == REC_TYPE_XTRA) { + state->mime_errs = mime_state_update(state->mime_state, type, buf, len); if (state->milters || cleanup_milters) /* Make room for body modification. */ cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT, 0L); - state->mime_errs = mime_state_update(state->mime_state, type, buf, len); /* Ignore header truncation after primary message headers. */ state->mime_errs &= ~MIME_ERR_TRUNC_HEADER; if (state->mime_errs && state->reason == 0) { diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 3c334f4f5..44bb8bfd5 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20060824" +#define MAIL_RELEASE_DATE "20060825" #define MAIL_VERSION_NUMBER "2.4" #ifdef SNAPSHOT diff --git a/postfix/src/global/record.c b/postfix/src/global/record.c index 6e4a78dcb..a52003e75 100644 --- a/postfix/src/global/record.c +++ b/postfix/src/global/record.c @@ -293,18 +293,42 @@ int rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags) int rec_goto(VSTREAM *stream, const char *buf) { off_t offset; + static const char *saved_path; + static off_t saved_offset; + static int reverse_count; + /* + * Crude workaround for queue file loops. VSTREAMs currently have no + * option to attach application-specific data, so we use global state and + * simple logic to detect if an application switches streams. We trigger + * on reverse jumps only. There's one reverse jump for every inserted + * header, but only one reverse jump for all appended recipients. No-one + * is likely to insert 10000 message headers, but someone might append + * 10000 recipients. + */ +#define STREQ(x,y) ((x) == (y) && strcmp((x), (y)) == 0) +#define REVERSE_JUMP_LIMIT 10000 + + if (!STREQ(saved_path, VSTREAM_PATH(stream))) { + saved_path = VSTREAM_PATH(stream); + reverse_count = 0; + saved_offset = 0; + } while (ISSPACE(*buf)) buf++; if ((offset = off_cvt_string(buf)) < 0) { msg_warn("%s: malformed pointer record value: %s", VSTREAM_PATH(stream), buf); return (REC_TYPE_ERROR); + } else if (offset < saved_offset && ++reverse_count > REVERSE_JUMP_LIMIT) { + msg_warn("%s: too many reverse jump records", VSTREAM_PATH(stream)); + return (REC_TYPE_ERROR); } else if (offset > 0 && vstream_fseek(stream, offset, SEEK_SET) < 0) { msg_warn("%s: seek error after pointer record: %m", VSTREAM_PATH(stream)); return (REC_TYPE_ERROR); } else { + saved_offset = offset; return (0); } } diff --git a/postfix/src/smtpstone/smtp-sink.c b/postfix/src/smtpstone/smtp-sink.c index faa7861f8..f89fae7e7 100644 --- a/postfix/src/smtpstone/smtp-sink.c +++ b/postfix/src/smtpstone/smtp-sink.c @@ -113,6 +113,10 @@ /* DATA, ., RSET, NOOP, and QUIT. Separate command names by /* white space or commas, and use quotes to protect white space /* from the shell. Command names are case-insensitive. +/* .IP "\fB-R \fIroot-directory\fR" +/* Change the process root directory to the specified location. +/* This option requires super-user privileges. See also the +/* \fB-u\fR option. /* .IP "\fB-s \fIcommand,command,...\fR" /* Log the named commands to syslogd. /* .sp @@ -131,6 +135,11 @@ /* .IP "\fB-t \fItimeout\fR (default: 100)" /* Limit the time for receiving a command or sending a response. /* The time limit is specified in seconds. +/* .IP "\fB-u \fIusername\fR" +/* Switch to the specified user privileges after opening the +/* network socket and optionally changing the process root +/* directory. This option is required when the process runs +/* with super-user privileges. See also the \fB-R\fR option. /* .IP \fB-v\fR /* Show the SMTP conversations. /* .IP "\fB-w \fIdelay\fR" @@ -1193,7 +1202,7 @@ static void connect_event(int unused_event, char *unused_context) static void usage(char *myname) { - msg_fatal("usage: %s [-468acCeEFLpPv] [-f commands] [-h hostname] [-m max_concurrency] [-n quit_count] [-q commands] [-r commands] [-s commands] [-w delay] [-d dump-template] [-D dump-template] [-S start-string] [host]:port backlog", myname); + msg_fatal("usage: %s [-468acCeEFLpPv] [-f commands] [-h hostname] [-m max_concurrency] [-n quit_count] [-q commands] [-r commands] [-s commands] [-w delay] [-d dump-template] [-D dump-template] [-R root-dir] [-S start-string] [-u user_privs] [host]:port backlog", myname); } int main(int argc, char **argv) @@ -1202,6 +1211,8 @@ int main(int argc, char **argv) int ch; const char *protocols = INET_PROTO_NAME_ALL; INET_PROTO_INFO *proto_info; + const char *root_dir = 0; + const char *user_privs = 0; /* * Fix 20051207. @@ -1216,7 +1227,7 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "468acCeEf:Fh:Ln:m:pPq:r:s:S:t:vw:d:D:")) > 0) { + while ((ch = GETOPT(argc, argv, "468acCd:D:eEf:Fh:Ln:m:pPq:r:R:s:S:t:u:vw:")) > 0) { switch (ch) { case '4': protocols = INET_PROTO_NAME_IPV4; @@ -1285,6 +1296,9 @@ int main(int argc, char **argv) set_cmds_flags(optarg, FLAG_SOFT_ERR); disable_pipelining = 1; break; + case 'R': + root_dir = optarg; + break; case 's': openlog(basename(argv[0]), LOG_PID, LOG_MAIL); set_cmds_flags(optarg, FLAG_SYSLOG); @@ -1297,6 +1311,9 @@ int main(int argc, char **argv) if ((var_tmout = atoi(optarg)) <= 0) msg_fatal("bad timeout: %s", optarg); break; + case 'u': + user_privs = optarg; + break; case 'v': msg_verbose++; break; @@ -1314,6 +1331,8 @@ int main(int argc, char **argv) usage(argv[0]); if (single_template && shared_template) msg_fatal("use only one of -d or -D, but not both"); + if (geteuid() == 0 && user_privs == 0) + msg_fatal("-u option is required if running as root"); /* * Initialize. @@ -1331,6 +1350,8 @@ int main(int argc, char **argv) argv[optind] += 5; sock = inet_listen(argv[optind], backlog, BLOCKING); } + if (user_privs) + chroot_uid(root_dir, user_privs); if (single_template) mysrand((int) time((time_t *) 0));