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.
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 <db.h> and by linking with -ldb
+ echo "No <db.h> 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
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."
/* 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
/* 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
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);
+}
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 *);
* 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
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) {
*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;
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) == '/') {
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;
/*
* Skip blank lines and comment lines.
*/
- do {
+ for (;;) {
if (readlline(buf, master_fp, &master_line) == 0) {
vstring_free(buf);
vstring_free(junk);
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
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;
int mime_errs = 0;
MILTER_MSG_CONTEXT msg_ctx;
VSTRING *buf;
+ int saved_errno;
switch (milter->state) {
case MILTER8_STAT_ERROR:
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;
*/
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 *);
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
}
/*
- * 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
*/
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.
*/
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 *);
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
}
/*
- * 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
*/
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.
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);
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);
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);
}
/*
* LINUX.
*/
-#ifdef LINUX2
+#if defined(LINUX2) || defined(LINUX3)
#define SUPPORTED
#include <sys/types.h>
#define UINT32_TYPE unsigned int