2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +00:00

postfix-2.5.12

This commit is contained in:
Wietse Venema 2011-03-03 00:00:00 -05:00 committed by Viktor Dukhovni
parent b3ab42ccc0
commit f6a26a3518
12 changed files with 246 additions and 37 deletions

View File

@ -14571,6 +14571,18 @@ Apologies for any names omitted.
2821 (and 5321) is vague about the VRFY request format, but
spends lots of text on the reply format. File: smtpd/smtpd.c.
20100422
Workaround (introduced: postfix-19990906 a.k.a. Postfix
0.8.0). The Postfix local delivery agent did not properly
distinguish between "address has no extension" and "address
has an extension, but the extension is invalid". In both
cases it would run only the full recipient local-part through
the alias maps. Instead, it now drops the faulty extension
from the recipient address local-part (it would be too
error-prone to replace all tests for "no extension" by tests
for "no valid extension". File: local/recipient.c.
20100610
Bugfix (introduced Postfix 2.2): Postfix no longer appends
@ -14610,3 +14622,59 @@ Apologies for any names omitted.
compliance. We now make an exception for "final" replies,
as permitted by RFC. Solution by Victor Duchovni. File:
smtpd/smtpd.c.
20101201
Workaround: BSD-ish mkdir() ignores the effective GID and
copies group ownership from the parent directory. File:
util/make_dirs.c.
20101202
Cleanup: the cleanup server now reports a temporary delivery
error when it reaches the virtual_alias_expansion_limit or
virtual_alias_recursion_limit. Previously, it would silently
ignore the excess recipients and deliver the message. File:
cleanup/cleanup_map1n.c.
20110105
Bugfix (introduced with the Postfix TLS patch): discard
plaintext following the STARTTLS command or response. This
matters only for the minority of SMTP clients that actually
verify server certificates. Files: smtpd/smtpd.c,
smtp/smtp_proto.c.
This vulnerability is also known as CVE-2011-0411.
20110109
Bugfix (introduced Postfix 2.4): on Solaris the Postfix
event engine was deaf for SIGHUP and SIGALRM signals after
the switch to /dev/poll. Symptoms were delayed "postfix
reload" response, and killed processes when the watchdog
timeout was less than max_idle. The fix is to set up SIGHUP
and SIGALRM handlers that write to a pipe, and to monitor
that pipe for read events via the Postfix event engine.
Files: master/master_sig.c, util/watchdog.c, util/sys_defs.h.
20110117
Bugfix (introduced Postfix alpha, or thereabouts): on HP-UX
the Postfix event engine was deaf for SIGALRM signals.
Symptoms were killed processes when the watchdog timeout
was less than max_idle. The fix is the same as Solaris fix
20110109. Since we can't know what other systems need this,
the workaround is enabled by default. Files: util/sys_defs.h.
20110225
Workaround (problem introduced with IPv6 support in Postfix
2.2): the SMTP client did not support mail to [ipv6:ipv6addr].
Fix based on a patch by Gurusamy Sarathy (Sophos). File:
util/host_port.c and regression test files.
20110227
Portability: FreeBSD closefrom() support time window. Sahil
Tandon. File: util/sys_defs.h.

View File

@ -214,6 +214,12 @@ case "$SYSTEM.$RELEASE" in
done
;;
AIX.*) case "`uname -v`" in
6) SYSTYPE=AIX6
case "$CC" in
cc|*/cc|xlc|*/xlc) CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
esac
CCARGS="$CCARGS -D_ALL_SOURCE -DHAS_POSIX_REGEXP"
;;
5) SYSTYPE=AIX5
case "$CC" in
cc|*/cc|xlc|*/xlc) CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;

View File

@ -15,13 +15,18 @@
/* This module implements one-to-many table mapping via table lookup.
/* Table lookups are done with quoted (externalized) address forms.
/* The process is recursive. The recursion terminates when the
/* left-hand side appears in its own expansion, or when a maximal
/* nesting level is reached.
/* left-hand side appears in its own expansion.
/*
/* cleanup_map1n_internal() is the interface for addresses in
/* internal (unquoted) form.
/* DIAGNOSTICS
/* Recoverable errors: the global \fIcleanup_errs\fR flag is updated.
/* When the maximal expansion or recursion limit is reached,
/* the alias is not expanded and the CLEANUP_STAT_DEFER error
/* is raised with reason "4.6.0 Alias expansion error".
/*
/* When table lookup fails, the alias is not expanded and the
/* CLEANUP_STAT_WRITE error is raised with reason "4.6.0 Alias
/* expansion error".
/* SEE ALSO
/* mail_addr_map(3) address mappings
/* mail_addr_find(3) address lookups
@ -93,15 +98,26 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
* must index the array explicitly, instead of running along it with a
* pointer.
*/
#define UPDATE(ptr,new) { myfree(ptr); ptr = mystrdup(new); }
#define UPDATE(ptr,new) do { \
if (ptr) myfree(ptr); ptr = mystrdup(new); \
} while (0)
#define STR vstring_str
#define RETURN(x) { been_here_free(been_here); return (x); }
#define RETURN(x) do { \
been_here_free(been_here); return (x); \
} while (0)
#define UNEXPAND(argv, addr) do { \
argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \
} while (0)
for (arg = 0; arg < argv->argc; arg++) {
if (argv->argc > var_virt_expan_limit) {
msg_warn("%s: unreasonable %s map expansion size for %s",
msg_warn("%s: unreasonable %s map expansion size for %s -- "
"deferring delivery",
state->queue_id, maps->title, addr);
break;
state->errs |= CLEANUP_STAT_DEFER;
UPDATE(state->reason, "4.6.0 Alias expansion error");
UNEXPAND(argv, addr);
RETURN(argv);
}
for (count = 0; /* void */ ; count++) {
@ -111,9 +127,13 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
if (been_here_check_fixed(been_here, argv->argv[arg]) != 0)
break;
if (count >= var_virt_recur_limit) {
msg_warn("%s: unreasonable %s map nesting for %s",
msg_warn("%s: unreasonable %s map nesting for %s -- "
"deferring delivery",
state->queue_id, maps->title, addr);
break;
state->errs |= CLEANUP_STAT_DEFER;
UPDATE(state->reason, "4.6.0 Alias expansion error");
UNEXPAND(argv, addr);
RETURN(argv);
}
quote_822_local(state->temp1, argv->argv[arg]);
if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) {
@ -136,9 +156,12 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
myfree(saved_lhs);
argv_free(lookup);
} else if (dict_errno != 0) {
msg_warn("%s: %s map lookup problem for %s",
msg_warn("%s: %s map lookup problem for %s -- "
"deferring delivery",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_WRITE;
UPDATE(state->reason, "4.6.0 Alias expansion error");
UNEXPAND(argv, addr);
RETURN(argv);
} else {
break;

View File

@ -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 "20101123"
#define MAIL_VERSION_NUMBER "2.5.11"
#define MAIL_RELEASE_DATE "20110303"
#define MAIL_VERSION_NUMBER "2.5.12"
#ifdef SNAPSHOT
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE

View File

@ -287,6 +287,10 @@ int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
/*
* Address extension management.
*
* XXX Fix 20100422, finalized 20100529: it is too error-prone to
* distinguish between "no extension" and "no valid extension", so we
* drop an invalid extension from the recipient address local-part.
*/
state.msg_attr.user = mystrdup(state.msg_attr.local);
if (*var_rcpt_delim) {
@ -296,6 +300,9 @@ int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
msg_warn("%s: address with illegal extension: %s",
state.msg_attr.queue_id, state.msg_attr.local);
state.msg_attr.extension = 0;
/* XXX Can't myfree + mystrdup, must truncate instead. */
state.msg_attr.local[strlen(state.msg_attr.user)] = 0;
/* Truncating is safe. The code below rejects null usernames. */
}
} else
state.msg_attr.extension = 0;

View File

@ -53,9 +53,8 @@
#ifdef USE_SIG_RETURN
#include <sys/syscall.h>
#endif
#ifndef USE_SIG_RETURN
#undef USE_SIG_PIPE
#else
#define USE_SIG_PIPE
#endif
@ -76,6 +75,8 @@ int master_sig_pipe[2];
int master_gotsigchld;
int master_gotsighup;
#ifdef USE_SIG_RETURN
/* master_sighup - register arrival of hangup signal */
static void master_sighup(int sig)
@ -92,8 +93,6 @@ static void master_sighup(int sig)
/* master_sigchld - register arrival of child death signal */
#ifdef USE_SIG_RETURN
static void master_sigchld(int sig, int code, struct sigcontext * scp)
{
@ -116,7 +115,25 @@ static void master_sigchld(int sig, int code, struct sigcontext * scp)
#else
#ifdef USE_SIG_PIPE
/* master_sighup - register arrival of hangup signal */
static void master_sighup(int sig)
{
int saved_errno = errno;
/*
* WARNING WARNING WARNING.
*
* This code runs at unpredictable moments, as a signal handler. Don't put
* any code here other than for setting a global flag, or code that is
* intended to be run within a signal handler. Restore errno in case we
* are interrupting the epilog of a failed system call.
*/
master_gotsighup = sig;
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
errno = saved_errno;
}
/* master_sigchld - force wakeup from select() */
@ -132,6 +149,7 @@ static void master_sigchld(int unused_sig)
* intended to be run within a signal handler. Restore errno in case we
* are interrupting the epilog of a failed system call.
*/
master_gotsigchld = 1;
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
errno = saved_errno;
@ -145,24 +163,8 @@ static void master_sig_event(int unused_event, char *unused_context)
while (read(SIG_PIPE_READ_FD, c, 1) > 0)
/* void */ ;
master_gotsigchld = 1;
}
#else
static void master_sigchld(int sig)
{
/*
* WARNING WARNING WARNING.
*
* This code runs at unpredictable moments, as a signal handler. Don't put
* any code here other than for setting a global flag.
*/
master_gotsigchld = sig;
}
#endif
#endif
/* master_sigdeath - die, women and children first */

View File

@ -811,6 +811,9 @@ static int smtp_start_tls(SMTP_STATE *state)
SMTP_RESP_FAKE(&fake, "4.7.5"),
"Server certificate not verified"));
/* At this point there must not be any pending plaintext. */
vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH);
/*
* At this point we have to re-negotiate the "EHLO" to reget the
* feature-list.

View File

@ -3911,6 +3911,8 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
/* Flush before we switch the stream's read/write routines. */
smtp_flush(state->client);
/* At this point there must not be any pending plaintext. */
vstream_fpurge(state->client, VSTREAM_PURGE_BOTH);
/*
* Reset all inputs to the initial state.

View File

@ -95,22 +95,41 @@
#include <host_port.h>
/*
* Point-fix workaround. The libutil library should be email agnostic, but
* we can't rip up the library APIs in the stable releases.
*/
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#define IPV6_COL "IPv6:" /* RFC 2821 */
#define IPV6_COL_LEN (sizeof(IPV6_COL) - 1)
#define HAS_IPV6_COL(str) (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
/* host_port - parse string into host and port, destroy string */
const char *host_port(char *buf, char **host, char *def_host,
char **port, char *def_service)
{
char *cp = buf;
int ipv6 = 0;
/*
* [host]:port, [host]:, [host].
* [ipv6:ipv6addr]:port, [ipv6:ipv6addr]:, [ipv6:ipv6addr].
*/
if (*cp == '[') {
*host = ++cp;
++cp;
if ((ipv6 = HAS_IPV6_COL(cp)) != 0)
cp += IPV6_COL_LEN;
*host = cp;
if ((cp = split_at(cp, ']')) == 0)
return ("missing \"]\"");
if (*cp && *cp++ != ':')
return ("garbage after \"]\"");
if (ipv6 && !valid_ipv6_hostaddr(*host, DONT_GRIPE))
return ("malformed IPv6 address");
*port = *cp ? cp : def_service;
}

View File

@ -37,6 +37,7 @@
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
/* Utility library. */
@ -49,12 +50,14 @@
int make_dirs(const char *path, int perms)
{
const char *myname = "make_dirs";
char *saved_path;
unsigned char *cp;
int saved_ch;
struct stat st;
int ret;
mode_t saved_mode = 0;
gid_t egid = -1;
/*
* Initialize. Make a copy of the path that we can safely clobber.
@ -117,6 +120,21 @@ int make_dirs(const char *path, int perms)
break;
}
}
/*
* Fix directory ownership when mkdir() ignores the effective
* GID. Don't change the effective UID for doing this.
*/
if ((ret = stat(saved_path, &st)) < 0) {
msg_warn("%s: stat %s: %m", myname, saved_path);
break;
}
if (egid == -1)
egid = getegid();
if (st.st_gid != egid && (ret = chown(saved_path, -1, egid)) < 0) {
msg_warn("%s: chgrp %s: %m", myname, saved_path);
break;
}
}
if (saved_ch != 0)
*cp = saved_ch;

View File

@ -111,7 +111,8 @@
#define HAS_DUPLEX_PIPE /* 4.1 breaks with kqueue(2) */
#endif
#if __FreeBSD_version >= 800098 /* commit: r194262 */
#if (__FreeBSD_version >= 702104 && __FreeBSD_version <= 800000) \
|| __FreeBSD_version >= 800100
#define HAS_CLOSEFROM
#endif
@ -506,7 +507,7 @@ extern int opterr;
* AIX: a SYSV-flavored hybrid. NB: fcntl() and flock() access the same
* underlying locking primitives.
*/
#ifdef AIX5
#if defined(AIX5) || defined(AIX6)
#define SUPPORTED
#include <sys/types.h>
#define UINT32_TYPE unsigned int
@ -1261,6 +1262,17 @@ extern int dup2_pass_on_exec(int oldd, int newd);
extern const char *inet_ntop(int, const void *, char *, size_t);
extern int inet_pton(int, const char *, void *);
#endif
/*
* Workaround: after a watchdog alarm signal, wake up from select/poll/etc.
* by writing to a pipe. Solaris needs this, and HP-UX apparently, too. The
* run-time cost is negligible so we just turn it on for all systems. As a
* side benefit, making this code system-independent will simplify the
* detection of bit-rot problems.
*/
#ifndef NO_WATCHDOG_PIPE
#define USE_WATCHDOG_PIPE
#endif
/*

View File

@ -119,6 +119,31 @@ struct WATCHDOG {
*/
static WATCHDOG *watchdog_curr;
/*
* Workaround for systems where the alarm signal does not wakeup the event
* machinery, and therefore does not restart the watchdog timer in the
* single_server etc. skeletons. The symptom is that programs abort when the
* watchdog timeout is less than the max_idle time.
*/
#ifdef USE_WATCHDOG_PIPE
#include <errno.h>
#include <iostuff.h>
#include <events.h>
static int watchdog_pipe[2];
/* watchdog_read - read event pipe */
static void watchdog_read(int unused_event, char *unused_context)
{
char ch;
while (read(watchdog_pipe[0], &ch, 1) > 0)
/* void */ ;
}
#endif /* USE_WATCHDOG_PIPE */
/* watchdog_event - handle timeout event */
static void watchdog_event(int unused_sig)
@ -137,6 +162,14 @@ static void watchdog_event(int unused_sig)
if (msg_verbose > 1)
msg_info("%s: %p %d", myname, (void *) wp, wp->trip_run);
if (++(wp->trip_run) < WATCHDOG_STEPS) {
#ifdef USE_WATCHDOG_PIPE
int saved_errno = errno;
/* Wake up the events(3) engine. */
if (write(watchdog_pipe[1], "", 1) != 1)
msg_warn("%s: write watchdog_pipe: %m", myname);
errno = saved_errno;
#endif
alarm(wp->timeout);
} else {
if (wp->action)
@ -177,6 +210,15 @@ WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context)
msg_fatal("%s: sigaction(SIGALRM): %m", myname);
if (msg_verbose > 1)
msg_info("%s: %p %d", myname, (void *) wp, timeout);
#ifdef USE_WATCHDOG_PIPE
if (watchdog_curr == 0) {
if (pipe(watchdog_pipe) < 0)
msg_fatal("%s: pipe: %m", myname);
non_blocking(watchdog_pipe[0], NON_BLOCKING);
non_blocking(watchdog_pipe[1], NON_BLOCKING);
event_enable_read(watchdog_pipe[0], watchdog_read, (char *) 0);
}
#endif
return (watchdog_curr = wp);
}
@ -193,6 +235,13 @@ void watchdog_destroy(WATCHDOG *wp)
if (wp->saved_time)
alarm(wp->saved_time);
myfree((char *) wp);
#ifdef USE_WATCHDOG_PIPE
if (watchdog_curr == 0) {
event_disable_readwrite(watchdog_pipe[0]);
(void) close(watchdog_pipe[0]);
(void) close(watchdog_pipe[1]);
}
#endif
if (msg_verbose > 1)
msg_info("%s: %p", myname, (void *) wp);
}