From 4dee1483aae95a25fde02b005b9a9bb40cd64672 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Thu, 7 Jul 2011 00:00:00 -0500 Subject: [PATCH] postfix-2.6.11 --- postfix/HISTORY | 45 +++++++++++++++++++++++++ postfix/makedefs | 27 +++++++++++++++ postfix/postfix-install | 2 +- postfix/src/global/abounce.c | 30 ++++++++++++++++- postfix/src/global/abounce.h | 1 + postfix/src/global/mail_version.h | 4 +-- postfix/src/local/mailbox.c | 11 +++++++ postfix/src/local/unknown.c | 5 +++ postfix/src/master/master_ent.c | 8 +++-- postfix/src/milter/milter8.c | 7 +++- postfix/src/oqmgr/qmgr_active.c | 55 ++++++++++++++++++++++--------- postfix/src/qmgr/qmgr_active.c | 55 ++++++++++++++++++++++--------- postfix/src/smtpd/smtpd_check.c | 15 +++++++-- postfix/src/util/sys_defs.h | 2 +- 14 files changed, 223 insertions(+), 44 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 320a72dc8..833a4c119 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -15482,3 +15482,48 @@ Apologies for any names omitted. reuse a server SASL handle after authentication failure. Problem reported by Thomas Jarosch of Intra2net AG. File: smtpd/smtpd_proto.c. + +20110418 + + Bugfix (introduced Postfix 2.3): the Milter client reported + some "file too large" errors as temporary errors. Problem + reported by Michael Tokarev. File: milter/milter8.c. + +20110420 + + Performance: a high load of DSN success notification requests + could slow down the queue manager. Solution: make the trace + client asynchronous, just like the bounce and defer clients. + Problem reported by Eduardo M. Stelmaszczyk of terra.com.br. + Files: global/abounce.[hc], *qmgr/qmgr_active.c (the + qmgr_active.c files are identical). + +20110426 + + Bugfix (introduced in Postfix 1.1): the local(8) delivery + agent ignored table lookup errors in mailbox_command_maps, + mailbox_transport_maps, and fallback_transport_maps. Problem + reported by William Ono. Files: local/command.c, local/mailbox.c, + local/unknown.c. + +20110601 + + Cleanup: don't supply the "-o stress" command-line option + with a single-process service. File: master/master_ent.c. + + Bugfix (introduced Postfix 2.6 with master_service_disable) + loop control error when parsing a malformed master.cf file. + Found by Coverity. File: master/master_ent.c. + +20110614 + + Linux kernel version 3 support. Linus Torvalds has reset + the counters for reasons not related to changes in code. + Files: makedefs, util/sys_defs.h. + +20110615 + + Workaround: some Spamhaus RHSBL rejects lookups with "No + IP queries" even if the name has an alphanumerical prefix. + We play safe, and skip RHSBL queries for names ending in a + numerical suffix. File: smtpd/smtpd_check.c. diff --git a/postfix/makedefs b/postfix/makedefs index 3dbd99776..137ec7156 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -331,6 +331,33 @@ EOF rm -f makedefs.test makedefs.test.[co];; esac ;; + Linux.3*) SYSTYPE=LINUX3 + if [ -f /usr/include/db.h ] + then + : we are all set + elif [ -f /usr/include/db/db.h ] + then + CCARGS="$CCARGS -I/usr/include/db" + else + # On a properly installed system, Postfix builds + # by including and by linking with -ldb + echo "No include file found." 1>&2 + echo "Install the appropriate db*-devel package first." 1>&2 + echo "See the RELEASE_NOTES file for more information." 1>&2 + exit 1 + fi + SYSLIBS="-ldb" + for name in nsl resolv + do + for lib in /usr/lib64 /lib64 /usr/lib /lib + do + test -e $lib/lib$name.a -o -e $lib/lib$name.so && { + SYSLIBS="$SYSLIBS -l$name" + break + } + done + done + ;; GNU.0*|GNU/kFreeBSD.[567]*) SYSTYPE=GNU0 # Postfix no longer needs DB 1.85 compatibility diff --git a/postfix/postfix-install b/postfix/postfix-install index f936b81a0..775b0acfe 100644 --- a/postfix/postfix-install +++ b/postfix/postfix-install @@ -305,7 +305,7 @@ esac install_root_prompt="the prefix for installed file names. Specify this ONLY if you are building ready-to-install packages for -distribution to other machines." +distribution to OTHER machines. See PACKAGE_README for instructions." tempdir_prompt="a directory for scratch files while installing Postfix. You must have write permission in this directory." diff --git a/postfix/src/global/abounce.c b/postfix/src/global/abounce.c index 8c3169426..105b9f6b8 100644 --- a/postfix/src/global/abounce.c +++ b/postfix/src/global/abounce.c @@ -67,9 +67,21 @@ /* int dsn_ret; /* void (*callback)(int status, char *context); /* char *context; +/* +/* void atrace_flush(flags, queue, id, encoding, sender, +/* dsn_envid, dsn_ret, callback, context) +/* int flags; +/* const char *queue; +/* const char *id; +/* const char *encoding; +/* const char *sender; +/* const char *dsn_envid; +/* int dsn_ret; +/* void (*callback)(int status, char *context); +/* char *context; /* DESCRIPTION /* This module implements an asynchronous interface to the -/* bounce/defer service for submitting sender notifications +/* bounce/defer/trace service for submitting sender notifications /* without waiting for completion of the request. /* /* abounce_flush() bounces the specified message to @@ -92,6 +104,10 @@ /* the specified sender, including the defer log that was /* built with defer_append(). /* +/* atrace_flush() returns the specified message to the specified +/* sender, including the message delivery record log that was +/* built with vtrace_append(). +/* /* Arguments: /* .IP flags /* The bitwise OR of zero or more of the following (specify @@ -359,3 +375,15 @@ void adefer_warn(int flags, const char *queue, const char *id, flags, queue, id, encoding, sender, dsn_envid, dsn_ret, callback, context); } + +/* atrace_flush - asynchronous trace flush */ + +void atrace_flush(int flags, const char *queue, const char *id, + const char *encoding, const char *sender, + const char *dsn_envid, int dsn_ret, + ABOUNCE_FN callback, char *context) +{ + abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE, + flags, queue, id, encoding, sender, dsn_envid, dsn_ret, + callback, context); +} diff --git a/postfix/src/global/abounce.h b/postfix/src/global/abounce.h index 521499cf3..dc4264b6b 100644 --- a/postfix/src/global/abounce.h +++ b/postfix/src/global/abounce.h @@ -24,6 +24,7 @@ typedef void (*ABOUNCE_FN) (int, char *); extern void abounce_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); extern void adefer_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); extern void adefer_warn(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); +extern void atrace_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); extern void abounce_flush_verp(int, const char *, const char *, const char *, const char *, const char *, int, const char *, ABOUNCE_FN, char *); extern void adefer_flush_verp(int, const char *, const char *, const char *, const char *, const char *, int, const char *, ABOUNCE_FN, char *); diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 02800888c..c7f7788b7 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20110509" -#define MAIL_VERSION_NUMBER "2.6.10" +#define MAIL_RELEASE_DATE "20110707" +#define MAIL_VERSION_NUMBER "2.6.11" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/local/mailbox.c b/postfix/src/local/mailbox.c index d35ef66b4..58b01f79f 100644 --- a/postfix/src/local/mailbox.c +++ b/postfix/src/local/mailbox.c @@ -278,6 +278,7 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) transp_maps = maps_create(VAR_MBOX_TRANSP_MAPS, var_mbox_transp_maps, DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB); /* The -1 is a hint for the down-stream deliver_completed() function. */ + dict_errno = 0; if (*var_mbox_transp_maps && (map_transport = maps_find(transp_maps, state.msg_attr.user, DICT_FLAG_NONE)) != 0) { @@ -285,6 +286,11 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) *statusp = deliver_pass(MAIL_CLASS_PRIVATE, map_transport, state.request, &state.msg_attr.rcpt); return (YES); + } else if (dict_errno != 0) { + /* Details in the logfile. */ + dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); + *statusp = DEL_STAT_DEFER; + return (YES); } if (*var_mailbox_transport) { state.msg_attr.rcpt.offset = -1L; @@ -319,10 +325,15 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps, DICT_FLAG_LOCK | DICT_FLAG_PARANOID); + dict_errno = 0; if (*var_mailbox_cmd_maps && (map_command = maps_find(cmd_maps, state.msg_attr.user, DICT_FLAG_NONE)) != 0) { status = deliver_command(state, usr_attr, map_command); + } else if (dict_errno != 0) { + /* Details in the logfile. */ + dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); + status = DEL_STAT_DEFER; } else if (*var_mailbox_command) { status = deliver_command(state, usr_attr, var_mailbox_command); } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') { diff --git a/postfix/src/local/unknown.c b/postfix/src/local/unknown.c index 068f9eed2..eb5bbf250 100644 --- a/postfix/src/local/unknown.c +++ b/postfix/src/local/unknown.c @@ -110,12 +110,17 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) transp_maps = maps_create(VAR_FBCK_TRANSP_MAPS, var_fbck_transp_maps, DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB); /* The -1 is a hint for the down-stream deliver_completed() function. */ + dict_errno = 0; if (*var_fbck_transp_maps && (map_transport = maps_find(transp_maps, state.msg_attr.user, DICT_FLAG_NONE)) != 0) { state.msg_attr.rcpt.offset = -1L; return (deliver_pass(MAIL_CLASS_PRIVATE, map_transport, state.request, &state.msg_attr.rcpt)); + } else if (dict_errno != 0) { + /* Details in the logfile. */ + dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); + return (DEL_STAT_DEFER); } if (*var_fallback_transport) { state.msg_attr.rcpt.offset = -1L; diff --git a/postfix/src/master/master_ent.c b/postfix/src/master/master_ent.c index a520b7d2f..cc0bb56d7 100644 --- a/postfix/src/master/master_ent.c +++ b/postfix/src/master/master_ent.c @@ -272,7 +272,7 @@ MASTER_SERV *get_master_ent() /* * Skip blank lines and comment lines. */ - do { + for (;;) { if (readlline(buf, master_fp, &master_line) == 0) { vstring_free(buf); vstring_free(junk); @@ -284,7 +284,9 @@ MASTER_SERV *get_master_ent() name = cp; transport = get_str_ent(&bufp, "transport type", (char *) 0); vstring_sprintf(junk, "%s.%s", name, transport); - } while (match_service_match(master_disable, vstring_str(junk)) != 0); + if (match_service_match(master_disable, vstring_str(junk)) == 0) + break; + } /* * Parse one logical line from the configuration file. Initialize service @@ -526,7 +528,7 @@ MASTER_SERV *get_master_ent() argv_add(serv->args, "-u", (char *) 0); if (chroot) argv_add(serv->args, "-c", (char *) 0); - if ((serv->flags & MASTER_FLAG_LOCAL_ONLY) == 0) { + if ((serv->flags & MASTER_FLAG_LOCAL_ONLY) == 0 && serv->max_proc > 1) { argv_add(serv->args, "-o", "stress=" CONFIG_BOOL_YES, (char *) 0); serv->stress_param_val = serv->args->argv[serv->args->argc - 1] + sizeof("stress=") - 1; diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index 6fea0f06a..21776ca8d 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -2462,6 +2462,7 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile, int mime_errs = 0; MILTER_MSG_CONTEXT msg_ctx; VSTRING *buf; + int saved_errno; switch (milter->state) { case MILTER8_STAT_ERROR: @@ -2475,8 +2476,12 @@ static const char *milter8_message(MILTER *m, VSTREAM *qfile, if (msg_verbose) msg_info("%s: message to milter %s", myname, milter->m.name); if (vstream_fseek(qfile, data_offset, SEEK_SET) < 0) { + saved_errno = errno; msg_warn("%s: vstream_fseek %s: %m", myname, VSTREAM_PATH(qfile)); - return ("450 4.3.0 Queue file write error"); + /* XXX This should be available from cleanup_strerror.c. */ + return (saved_errno == EFBIG ? + "552 5.3.4 Message file too big" : + "451 4.3.0 Queue file write error"); } msg_ctx.milter = milter; msg_ctx.eoh_macros = eoh_macros; diff --git a/postfix/src/oqmgr/qmgr_active.c b/postfix/src/oqmgr/qmgr_active.c index eeec88d3b..eea9d71d0 100644 --- a/postfix/src/oqmgr/qmgr_active.c +++ b/postfix/src/oqmgr/qmgr_active.c @@ -116,6 +116,8 @@ */ static void qmgr_active_done_2_bounce_flush(int, char *); static void qmgr_active_done_2_generic(QMGR_MESSAGE *); +static void qmgr_active_done_25_trace_flush(int, char *); +static void qmgr_active_done_25_generic(QMGR_MESSAGE *); static void qmgr_active_done_3_defer_flush(int, char *); static void qmgr_active_done_3_defer_warn(int, char *); static void qmgr_active_done_3_generic(QMGR_MESSAGE *); @@ -336,10 +338,8 @@ static void qmgr_active_done_2_bounce_flush(int status, char *context) static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) { - const char *myname = "qmgr_active_done_2_generic"; const char *path; struct stat st; - int status; /* * A delivery agent marks a queue file as corrupt by changing its @@ -372,10 +372,6 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) } /* - * As a temporary implementation, synchronously inform the sender of - * trace information. This will block for 10 seconds when the qmgr FIFO - * is full. - * * XXX With multi-recipient mail, some recipients may have NOTIFY=SUCCESS * and others not. Depending on what subset of recipients are delivered, * a trace file may or may not be created. Even when the last partial @@ -388,18 +384,45 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) */ if ((message->tflags & (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD)) || (message->rflags & QMGR_READ_FLAG_NOTIFY_SUCCESS)) { - status = trace_flush(message->tflags, - message->queue_name, - message->queue_id, - message->encoding, - message->sender, - message->dsn_envid, - message->dsn_ret); - if (status == 0 && message->tflags_offset) - qmgr_message_kill_record(message, message->tflags_offset); - message->flags |= status; + atrace_flush(message->tflags, + message->queue_name, + message->queue_id, + message->encoding, + message->sender, + message->dsn_envid, + message->dsn_ret, + qmgr_active_done_25_trace_flush, + (char *) message); + return; } + /* + * Asynchronous processing does not reach this point. + */ + qmgr_active_done_25_generic(message); +} + +/* qmgr_active_done_25_trace_flush - continue after atrace_flush() completion */ + +static void qmgr_active_done_25_trace_flush(int status, char *context) +{ + QMGR_MESSAGE *message = (QMGR_MESSAGE *) context; + + /* + * Process atrace_flush() status and continue processing. + */ + if (status == 0 && message->tflags_offset) + qmgr_message_kill_record(message, message->tflags_offset); + message->flags |= status; + qmgr_active_done_25_generic(message); +} + +/* qmgr_active_done_25_generic - continue processing */ + +static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) +{ + const char *myname = "qmgr_active_done_25_generic"; + /* * If we get to this point we have tried all recipients for this message. * If the message is too old, try to bounce it. diff --git a/postfix/src/qmgr/qmgr_active.c b/postfix/src/qmgr/qmgr_active.c index eeec88d3b..eea9d71d0 100644 --- a/postfix/src/qmgr/qmgr_active.c +++ b/postfix/src/qmgr/qmgr_active.c @@ -116,6 +116,8 @@ */ static void qmgr_active_done_2_bounce_flush(int, char *); static void qmgr_active_done_2_generic(QMGR_MESSAGE *); +static void qmgr_active_done_25_trace_flush(int, char *); +static void qmgr_active_done_25_generic(QMGR_MESSAGE *); static void qmgr_active_done_3_defer_flush(int, char *); static void qmgr_active_done_3_defer_warn(int, char *); static void qmgr_active_done_3_generic(QMGR_MESSAGE *); @@ -336,10 +338,8 @@ static void qmgr_active_done_2_bounce_flush(int status, char *context) static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) { - const char *myname = "qmgr_active_done_2_generic"; const char *path; struct stat st; - int status; /* * A delivery agent marks a queue file as corrupt by changing its @@ -372,10 +372,6 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) } /* - * As a temporary implementation, synchronously inform the sender of - * trace information. This will block for 10 seconds when the qmgr FIFO - * is full. - * * XXX With multi-recipient mail, some recipients may have NOTIFY=SUCCESS * and others not. Depending on what subset of recipients are delivered, * a trace file may or may not be created. Even when the last partial @@ -388,18 +384,45 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) */ if ((message->tflags & (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD)) || (message->rflags & QMGR_READ_FLAG_NOTIFY_SUCCESS)) { - status = trace_flush(message->tflags, - message->queue_name, - message->queue_id, - message->encoding, - message->sender, - message->dsn_envid, - message->dsn_ret); - if (status == 0 && message->tflags_offset) - qmgr_message_kill_record(message, message->tflags_offset); - message->flags |= status; + atrace_flush(message->tflags, + message->queue_name, + message->queue_id, + message->encoding, + message->sender, + message->dsn_envid, + message->dsn_ret, + qmgr_active_done_25_trace_flush, + (char *) message); + return; } + /* + * Asynchronous processing does not reach this point. + */ + qmgr_active_done_25_generic(message); +} + +/* qmgr_active_done_25_trace_flush - continue after atrace_flush() completion */ + +static void qmgr_active_done_25_trace_flush(int status, char *context) +{ + QMGR_MESSAGE *message = (QMGR_MESSAGE *) context; + + /* + * Process atrace_flush() status and continue processing. + */ + if (status == 0 && message->tflags_offset) + qmgr_message_kill_record(message, message->tflags_offset); + message->flags |= status; + qmgr_active_done_25_generic(message); +} + +/* qmgr_active_done_25_generic - continue processing */ + +static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) +{ + const char *myname = "qmgr_active_done_25_generic"; + /* * If we get to this point we have tried all recipients for this message. * If the message is too old, try to bounce it. diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 47cfd48c9..62ef75be0 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -3218,6 +3218,7 @@ static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain, SMTPD_RBL_STATE *rbl; const char *domain; const char *reply_addr; + const char *suffix; if (msg_verbose) msg_info("%s: %s %s", myname, reply_class, what); @@ -3232,7 +3233,16 @@ static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain, return (SMTPD_CHECK_DUNNO); } else domain = what; - if (domain[0] == 0) + + /* + * XXX Some Spamhaus RHSBL rejects lookups with "No IP queries" even if + * the name has an alphanumerical prefix. We play safe, and skip RHSBL + * queries for names ending in a numerical suffix. + */ + if (domain[0] == 0 || valid_hostname(domain, DONT_GRIPE) == 0) + return (SMTPD_CHECK_DUNNO); + suffix = strrchr(domain, '.'); + if (alldig(suffix == 0 ? domain : suffix + 1)) return (SMTPD_CHECK_DUNNO); query = vstring_alloc(100); @@ -3755,8 +3765,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, name); else { cpp += 1; - if (state->helo_name - && valid_hostname(state->helo_name, DONT_GRIPE)) + if (state->helo_name) status = reject_rbl_domain(state, *cpp, state->helo_name, SMTPD_NAME_HELO); } diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index 43c3dd7e3..67de2c7dd 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -703,7 +703,7 @@ extern int initgroups(const char *, int); /* * LINUX. */ -#ifdef LINUX2 +#if defined(LINUX2) || defined(LINUX3) #define SUPPORTED #include #define UINT32_TYPE unsigned int