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

postfix-2.11-20131114

This commit is contained in:
Wietse Venema 2013-11-14 00:00:00 -05:00 committed by Viktor Dukhovni
parent 9aa88be230
commit 897f730f14
40 changed files with 425 additions and 239 deletions

View File

@ -19069,7 +19069,45 @@ Apologies for any names omitted.
not hurt to do this also for HTML. Files: proto/Makefile.in,
proto/MULTI_INSTANCE_README.html.
20121104
20131104
Feature: ${queue_id} macro support for the pipe(8) delivery
agent by Andreas Schulze. File: pipe/pipe.c.
20131107
Cleanup: after 16 years the SKIP() and TRIM() macros were
triggering compiler warnings. Files: global/mail_params.c,
smtpstone/smtp-sink.c, util/mac_parse.c, util/split_nameval.c.
20131110
Bugfix (introduced Oct 26 1997): don't clobber errno before
expanding %m. File: util/vbuf_print.c.
20131114
Cleanup: LMDB >= 0.9.10 does not need the MDB_WRITEMAP
workaround to avoid heap memory information leaks. File:
util/dict_lmdb.c.
20131114
Cleanup: Coverity found a harmless memory leak in the
postconf master.cf parser. Reported by Christos Zoulas,
NetBSD. File: postconf/postconf_master.c.
Cleanup: graceful degradation after database open() error.
Several instances of that code introduced a harmless memory
leak, and Coverity complained about one of them (Christos
Zoulas, NetBSD). Instead of adding random code in random
places, restructured dict_foo_open() routines with consistent
code to dispose of memory or file handles. Files: dict_thash.c,
dict_sockmap.c, dict_regexp.c, dict_pcre.c, dict_lmdb.c,
dict_dbm.c, dict_cidr.c, dict_cdb.c.
Cleanup: warning message after canonical/virtal/etc.
table lookup error. Files: cleanup/cleanup_addr.c,
cleanup/cleanup_map11.c, cleanup/cleanup_map1n.c,
cleanup/cleanup_masquerade.c, cleanup/cleanup_message.c,
cleanup/cleanup_milter.c.

View File

@ -557,10 +557,10 @@ plaintext.
If you must store encrypted passwords, you cannot use the ldapdb auxprop
plugin. Instead, you can use "saslauthd -a ldap" to query the LDAP database
directly, with appropriate configuration in saslauthd.conf. This may be
documented in a later version of this document. You will not be able to use
any of the methods that require access to plaintext passwords, such as the
shared-secret methods CRAM-MD5 and DIGEST-MD5.
directly, with appropriate configuration in saslauthd.conf, as described
here. You will not be able to use any of the methods that require access to
plaintext passwords, such as the shared-secret methods CRAM-MD5 and DIGEST-
MD5.
The ldapdb plugin implements proxy authorization. This means that the ldapdb
plugin uses its own username and password to authenticate with the LDAP server,

View File

@ -1,8 +1,17 @@
Wish list:
Un-break "make tests" under src/smtpd.
Make been_here flag BH_FLAG_FOLD configurable for masochists.
Preserve case in smtpd_resolve_addr() and add a structure
member for the case-folded address.
Per SASL account rate limits.
Add watchdog timer to postmap/postalias.
Watchdog timer to postmap/postalias.
C99 va_copy() support.
Things to do before the stable release:

View File

@ -948,8 +948,9 @@ stored as plaintext. </p>
<p> If you must store encrypted passwords, you cannot use the ldapdb
auxprop plugin. Instead, you can use "<code>saslauthd -a ldap</code>"
to query the LDAP database directly, with appropriate configuration
in <code>saslauthd.conf</code>. This may be documented in a later
version of this document. You will not be able to use any of the
in <code>saslauthd.conf</code>, <a
href="http://git.cyrusimap.org/cyrus-sasl/tree/saslauthd/LDAP_SASLAUTHD">as
described here</a>. You will not be able to use any of the
methods that require access to plaintext passwords, such as the
shared-secret methods CRAM-MD5 and DIGEST-MD5. </p>

View File

@ -98,8 +98,8 @@ MASTER(5) MASTER(5)
trolled with the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configura-
tion parameter in <a href="postconf.5.html">main.cf</a>).
On Solaris systems the <b>unix</b> type is imple-
mented with streams sockets.
On Solaris 8 and earlier systems the <b>unix</b>
type is implemented with streams sockets.
<b>fifo</b> The service listens on a FIFO (named pipe)
and is accessible for local clients only.
@ -119,8 +119,8 @@ MASTER(5) MASTER(5)
trolled with the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configura-
tion parameter in <a href="postconf.5.html">main.cf</a>).
On Solaris systems the <b>pass</b> type is imple-
mented with streams sockets.
On Solaris 8 and earlier systems the <b>pass</b>
type is implemented with streams sockets.
This feature is available as of Postfix ver-
sion 2.5.
@ -225,8 +225,8 @@ MASTER(5) MASTER(5)
to understand and maintain. At a certain
point, it might be easier to configure mul-
tiple instances of Postfix, instead of con-
figuring multiple personalities via mas-
ter.cf.
figuring multiple personalities via <a href="master.5.html">mas-
ter.cf</a>.
<b>-v</b> Increase the verbose logging level. Specify
multiple <b>-v</b> options to make a Postfix daemon

View File

@ -12,7 +12,7 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>SYNOPSIS</b>
<b>smtp-sink</b> [<i>options</i>] [<b>inet:</b>][<i>host</i>]:<i>port backlog</i>
<b>smtp-sink</b> [<i>options</i>] <b>unix:</b><i>pathname backlog</i>
<b>smtp-sink</b> [<i>options</i>] <b>unix:<i></b>pathname backlog</i>
<b>DESCRIPTION</b>
<b>smtp-sink</b> listens on the named host (or address) and port.
@ -47,19 +47,19 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>-a</b> Do not announce SASL authentication support.
<b>-A</b> <i>delay</i>
<b>-A <i></b>delay
Wait <i>delay</i> seconds after responding to DATA, then
abort prematurely with a 550 reply status. Do not
read further input from the client; this is an
attempt to block the client before it sends ".".
Specify a zero delay value to abort immediately.
<b>-b</b> <i>soft-bounce-reply</i>
<b>-b <i></b>soft-bounce-reply
Use <i>soft-bounce-reply</i> for soft reject responses.
The default reply is "450 4.3.0 Error: command
failed".
<b>-B</b> <i>hard-bounce-reply</i>
<b>-B <i></b>hard-bounce-reply
Use <i>hard-bounce-reply</i> for hard reject responses.
The default reply is "500 5.3.0 Error: command
failed".
@ -70,7 +70,7 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>-C</b> Disable XCLIENT support.
<b>-d</b> <i>dump-template</i>
<b>-d <i></b>dump-template
Dump each mail transaction to a single-message file
whose name is created by expanding the <i>dump-tem-</i>
<i>plate</i> via strftime(3) and appending a pseudo-random
@ -83,7 +83,7 @@ SMTP-SINK(1) SMTP-SINK(1)
Note: this option keeps one capture file open for
every mail transaction in progress.
<b>-D</b> <i>dump-template</i>
<b>-D <i></b>dump-template
Append mail transactions to a multi-message dump
file whose name is created by expanding the <i>dump-</i>
<i>template</i> via strftime(3). If the template contains
@ -98,7 +98,7 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>-E</b> Do not announce ENHANCEDSTATUSCODES support.
<b>-f</b> <i>command,command,...</i>
<b>-f <i></b>command,command,...
Reject the specified commands with a hard (5xx)
error code. This option implies <b>-p</b>.
@ -110,24 +110,24 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>-F</b> Disable XFORWARD support.
<b>-h</b> <i>hostname</i>
<b>-h <i></b>hostname
Use <i>hostname</i> in the SMTP greeting, in the HELO
response, and in the EHLO response. The default
hostname is "smtp-sink".
<b>-L</b> Enable LMTP instead of SMTP.
<b>-m</b> <i>count</i> (default: 256)
<b>-m <i></b>count</i> (default: 256)
An upper bound on the maximal number of simultane-
ous connections that <b>smtp-sink</b> will handle. This
prevents the process from running out of file
descriptors. Excess connections will stay queued in
the TCP/IP stack.
<b>-M</b> <i>count</i>
<b>-M <i></b>count
Terminate after receiving <i>count</i> messages.
<b>-n</b> <i>count</i>
<b>-n <i></b>count
Terminate after <i>count</i> sessions.
<b>-p</b> Do not announce support for ESMTP command pipelin-
@ -136,7 +136,7 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>-P</b> Change the server greeting so that it appears to
come through a CISCO PIX system. Implies <b>-e</b>.
<b>-q</b> <i>command,command,...</i>
<b>-q <i></b>command,command,...
Disconnect (without replying) after receiving one
of the specified commands.
@ -146,7 +146,7 @@ SMTP-SINK(1) SMTP-SINK(1)
and use quotes to protect white space from the
shell. Command names are case-insensitive.
<b>-Q</b> <i>command,command,...</i>
<b>-Q <i></b>command,command,...
Send a 421 reply and disconnect after receiving one
of the specified commands.
@ -156,7 +156,7 @@ SMTP-SINK(1) SMTP-SINK(1)
and use quotes to protect white space from the
shell. Command names are case-insensitive.
<b>-r</b> <i>command,command,...</i>
<b>-r <i></b>command,command,...
Reject the specified commands with a soft (4xx)
error code. This option implies <b>-p</b>.
@ -166,12 +166,12 @@ SMTP-SINK(1) SMTP-SINK(1)
and use quotes to protect white space from the
shell. Command names are case-insensitive.
<b>-R</b> <i>root-directory</i>
<b>-R <i></b>root-directory
Change the process root directory to the specified
location. This option requires super-user privi-
leges. See also the <b>-u</b> option.
<b>-s</b> <i>command,command,...</i>
<b>-s <i></b>command,command,...
Log the named commands to syslogd.
Examples of commands are CONNECT, HELO, EHLO, LHLO,
@ -190,16 +190,16 @@ SMTP-SINK(1) SMTP-SINK(1)
tab), \<i>ddd</i> (up to three octal digits) and \\ (the
backslash character).
<b>-t</b> <i>timeout</i> (default: 100)
<b>-t <i></b>timeout</i> (default: 100)
Limit the time for receiving a command or sending a
response. The time limit is specified in seconds.
<b>-T</b> <i>windowsize</i>
<b>-T <i></b>windowsize
Override the default TCP window size. To work
around broken TCP window scaling implementations,
specify a value &gt; 0 and &lt; 65536.
<b>-u</b> <i>username</i>
<b>-u <i></b>username
Switch to the specified user privileges after open-
ing the network socket and optionally changing the
process root directory. This option is required
@ -208,11 +208,11 @@ SMTP-SINK(1) SMTP-SINK(1)
<b>-v</b> Show the SMTP conversations.
<b>-w</b> <i>delay</i>
<b>-w <i></b>delay
Wait <i>delay</i> seconds before responding to a DATA com-
mand.
<b>-W</b> <i>command:delay[:odds]</i>
<b>-W <i></b>command:delay[:odds]
Wait <i>delay</i> seconds before responding to <i>command</i>.
If <i>odds</i> is also specified (a number between 1-99
inclusive), wait for a random multiple of <i>delay</i>.
@ -226,7 +226,7 @@ SMTP-SINK(1) SMTP-SINK(1)
interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
specified in numeric or symbolic form.
<b>unix:</b><i>pathname</i>
<b>unix:<i></b>pathname
Listen on the UNIX-domain socket at <i>pathname</i>.
<i>backlog</i>
@ -251,45 +251,45 @@ SMTP-SINK(1) SMTP-SINK(1)
The format of the <b>smtp-sink</b> generated headers is as fol-
lows:
<b>X-Client-Addr:</b> <i>text</i>
<b>X-Client-Addr: <i></b>text
The client IP address without enclosing []. An IPv6
address is prefixed with "ipv6:". This record is
always present.
<b>X-Client-Proto:</b> <i>text</i>
<b>X-Client-Proto: <i></b>text
The client protocol: SMTP, ESMTP or LMTP. This
record is always present.
<b>X-Helo-Args:</b> <i>text</i>
<b>X-Helo-Args: <i></b>text
The arguments of the last HELO or EHLO command
before this mail delivery transaction. This record
is present only if the client sent a recognizable
HELO or EHLO command before the DATA command.
<b>X-Mail-Args:</b> <i>text</i>
<b>X-Mail-Args: <i></b>text
The arguments of the MAIL command that started this
mail delivery transaction. This record is present
exactly once.
<b>X-Rcpt-Args:</b> <i>text</i>
<b>X-Rcpt-Args: <i></b>text
The arguments of an RCPT command within this mail
delivery transaction. There is one record for each
RCPT command, and they are in the order as sent by
the client.
<b>Received:</b> <i>text</i>
<b>Received: <i></b>text
A message header for compatibility with mail pro-
cessing software. This three-line header marks the
end of the headers provided by <b>smtp-sink</b>, and is
formatted as follows:
<b>from</b> <i>helo</i> <b>([</b><i>addr</i><b>])</b>
<b>from <i></b>helo</i> <b>([<i></b>addr</i><b>])</b>
The HELO or EHLO command argument and client
IP address. If the client did not send HELO
or EHLO, the client IP address is used
instead.
<b>by</b> <i>host</i> <b>(smtp-sink) with</b> <i>proto</i> <b>id</b> <i>random</i><b>;</b>
<b>by <i></b>host</i> <b>(smtp-sink) with <i></b>proto</i> <b>id <i></b>random</i><b>;</b>
The hostname specified with the <b>-h</b> option,
the client protocol (see <b>X-Client-Proto</b>
above), and the pseudo-random portion of the

View File

@ -92,8 +92,8 @@ The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the \fBqueue_directory\fR
configuration parameter in main.cf).
.sp
On Solaris systems the \fBunix\fR type is implemented with
streams sockets.
On Solaris 8 and earlier systems the \fBunix\fR type is
implemented with streams sockets.
.IP \fBfifo\fR
The service listens on a FIFO (named pipe) and is accessible
for local clients only.
@ -110,8 +110,8 @@ The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the \fBqueue_directory\fR
configuration parameter in main.cf).
.sp
On Solaris systems the \fBpass\fR type is implemented with
streams sockets.
On Solaris 8 and earlier systems the \fBpass\fR type is
implemented with streams sockets.
This feature is available as of Postfix version 2.5.
.RE

View File

@ -948,8 +948,9 @@ stored as plaintext. </p>
<p> If you must store encrypted passwords, you cannot use the ldapdb
auxprop plugin. Instead, you can use "<code>saslauthd -a ldap</code>"
to query the LDAP database directly, with appropriate configuration
in <code>saslauthd.conf</code>. This may be documented in a later
version of this document. You will not be able to use any of the
in <code>saslauthd.conf</code>, <a
href="http://git.cyrusimap.org/cyrus-sasl/tree/saslauthd/LDAP_SASLAUTHD">as
described here</a>. You will not be able to use any of the
methods that require access to plaintext passwords, such as the
shared-secret methods CRAM-MD5 and DIGEST-MD5. </p>

View File

@ -86,8 +86,8 @@
# queue directory (pathname controlled with the \fBqueue_directory\fR
# configuration parameter in main.cf).
# .sp
# On Solaris systems the \fBunix\fR type is implemented with
# streams sockets.
# On Solaris 8 and earlier systems the \fBunix\fR type is
# implemented with streams sockets.
# .IP \fBfifo\fR
# The service listens on a FIFO (named pipe) and is accessible
# for local clients only.
@ -104,8 +104,8 @@
# queue directory (pathname controlled with the \fBqueue_directory\fR
# configuration parameter in main.cf).
# .sp
# On Solaris systems the \fBpass\fR type is implemented with
# streams sockets.
# On Solaris 8 and earlier systems the \fBpass\fR type is
# implemented with streams sockets.
#
# This feature is available as of Postfix version 2.5.
# .RE

View File

@ -149,7 +149,8 @@ void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
IGNORE_EXTENSION)) != 0) {
cleanup_addr_bcc(state, bcc);
} else if (cleanup_send_bcc_maps->error) {
msg_warn("%s: %s lookup problem",
msg_warn("%s: %s map lookup problem -- "
"message not accepted, try again later",
state->queue_id, cleanup_send_bcc_maps->title);
state->errs |= CLEANUP_STAT_WRITE;
}
@ -198,7 +199,8 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
IGNORE_EXTENSION)) != 0) {
cleanup_addr_bcc(state, bcc);
} else if (cleanup_rcpt_bcc_maps->error) {
msg_warn("%s: %s lookup problem",
msg_warn("%s: %s map lookup problem -- "
"message not accepted, try again later",
state->queue_id, cleanup_rcpt_bcc_maps->title);
state->errs |= CLEANUP_STAT_WRITE;
}

View File

@ -120,7 +120,8 @@ int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
if (expand_to_self)
return (did_rewrite);
} else if (maps->error != 0) {
msg_warn("%s: %s map lookup problem for %s",
msg_warn("%s: %s map lookup problem for %s -- "
"message not accepted, try again later",
state->queue_id, maps->title, STR(addr));
state->errs |= CLEANUP_STAT_WRITE;
return (did_rewrite);
@ -128,7 +129,8 @@ int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
return (did_rewrite);
}
}
msg_warn("%s: unreasonable %s map nesting for %s",
msg_warn("%s: unreasonable %s map nesting for %s -- "
"message not accepted, try again later",
state->queue_id, maps->title, STR(addr));
return (did_rewrite);
}

View File

@ -112,7 +112,7 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
for (arg = 0; arg < argv->argc; arg++) {
if (argv->argc > var_virt_expan_limit) {
msg_warn("%s: unreasonable %s map expansion size for %s -- "
"deferring delivery",
"message not accepted, try again later",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_DEFER;
UPDATE(state->reason, "4.6.0 Alias expansion error");
@ -128,7 +128,7 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
break;
if (count >= var_virt_recur_limit) {
msg_warn("%s: unreasonable %s map nesting for %s -- "
"deferring delivery",
"message not accepted, try again later",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_DEFER;
UPDATE(state->reason, "4.6.0 Alias expansion error");
@ -157,7 +157,7 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
argv_free(lookup);
} else if (maps->error != 0) {
msg_warn("%s: %s map lookup problem for %s -- "
"deferring delivery",
"message not accepted, try again later",
state->queue_id, maps->title, addr);
state->errs |= CLEANUP_STAT_WRITE;
UPDATE(state->reason, "4.6.0 Alias expansion error");

View File

@ -110,7 +110,8 @@ int cleanup_masquerade_external(CLEANUP_STATE *state, VSTRING *addr,
excluded = (string_list_match(cleanup_masq_exceptions, lowercase(name)) != 0);
myfree(name);
if (cleanup_masq_exceptions->error) {
msg_info("%s: %s lookup error -- deferring delivery",
msg_info("%s: %s map lookup problem -- "
"message not accepted, try again later",
state->queue_id, VAR_MASQ_EXCEPTIONS);
state->errs |= CLEANUP_STAT_WRITE;
}

View File

@ -499,7 +499,8 @@ static void cleanup_header_callback(void *context, int header_class,
myfree((char *) result);
}
} else if (checks->error) {
msg_warn("%s: %s map lookup problem -- deferring delivery",
msg_warn("%s: %s map lookup problem -- "
"message not accepted, try again later",
state->queue_id, checks->title);
state->errs |= CLEANUP_STAT_WRITE;
}
@ -789,7 +790,8 @@ static void cleanup_body_callback(void *context, int type,
return;
}
} else if (cleanup_body_checks->error) {
msg_warn("%s: %s map lookup problem -- deferring delivery",
msg_warn("%s: %s map lookup problem -- "
"message not accepted, try again later",
state->queue_id, cleanup_body_checks->title);
state->errs |= CLEANUP_STAT_WRITE;
}

View File

@ -392,7 +392,8 @@ static int cleanup_milter_header_checks(CLEANUP_STATE *state, VSTRING *buf)
if (ret == 0) {
return (0);
} else if (ret == HBC_CHECKS_STAT_ERROR) {
msg_warn("%s: %s lookup error -- deferring delivery",
msg_warn("%s: %s map lookup problem -- "
"message not accepted, try again later",
state->queue_id, VAR_MILT_HEAD_CHECKS);
state->errs |= CLEANUP_STAT_WRITE;
return (0);
@ -2092,7 +2093,7 @@ void cleanup_milter_emul_rcpt(CLEANUP_STATE *state,
&& cleanup_milter_apply(state, "RCPT", resp) != 0) {
msg_warn("%s: milter configuration error: can't reject recipient "
"in non-smtpd(8) submission", state->queue_id);
msg_warn("%s: deferring delivery of this message", state->queue_id);
msg_warn("%s: message not accepted, try again later", state->queue_id);
CLEANUP_MILTER_SET_REASON(state, "4.3.5 Server configuration error");
state->errs |= CLEANUP_STAT_DEFER;
}

View File

@ -487,14 +487,17 @@ static char *read_param_from_file(const char *path)
/*
* Ugly macros to make complex expressions less unreadable.
*/
#define SKIP(start, var, cond) \
for (var = start; *var && (cond); var++);
#define SKIP(start, var, cond) do { \
for (var = start; *var && (cond); var++) \
/* void */; \
} while (0)
#define TRIM(s) { \
#define TRIM(s) do { \
char *p; \
for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
/* void */; \
*p = 0; \
}
} while (0)
fp = safe_open(path, O_RDONLY, 0, (struct stat *) 0, -1, -1, why);
if (fp == 0)

View File

@ -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 "20131105"
#define MAIL_RELEASE_DATE "20131114"
#define MAIL_VERSION_NUMBER "2.11"
#ifdef SNAPSHOT

View File

@ -31,6 +31,9 @@
/* Terminate after \fIcount\fR connections.
/* .IP "\fB-d\fI level\fR"
/* Enable libmilter debugging at the specified level.
/* .IP "\fB-D\fI address\fR"
/* Delete the specified recipient address. Multiple -D options
/* are supported.
/* .IP "\fB-f \fIsender\fR
/* Replace the sender by the specified address.
/* .IP "\fB-h \fI'index header-label header-value'\fR"
@ -159,8 +162,10 @@ static char *body_file;
#endif
#define MAX_RCPT 10
int rcpt_count = 0;
char *rcpt_addr[MAX_RCPT];
int add_rcpt_count = 0;
char *add_rcpt[MAX_RCPT];
int del_rcpt_count = 0;
char *del_rcpt[MAX_RCPT];
static const char *macro_names[] = {
"_",
@ -354,9 +359,13 @@ static sfsistat test_eom(SMFICTX *ctx)
{
int count;
for (count = 0; count < rcpt_count; count++)
if (smfi_addrcpt(ctx, rcpt_addr[count]) == MI_FAILURE)
fprintf(stderr, "smfi_addrcpt `%s' failed\n", rcpt_addr[count]);
for (count = 0; count < add_rcpt_count; count++)
if (smfi_addrcpt(ctx, add_rcpt[count]) == MI_FAILURE)
fprintf(stderr, "smfi_addrcpt `%s' failed\n", add_rcpt[count]);
for (count = 0; count < del_rcpt_count; count++)
if (smfi_delrcpt(ctx, del_rcpt[count]) == MI_FAILURE)
fprintf(stderr, "smfi_delrcpt `%s' failed\n", del_rcpt[count]);
}
return (test_reply(ctx, test_eom_reply));
}
@ -540,17 +549,17 @@ int main(int argc, char **argv)
char *noreply = 0;
const struct noproto_map *np;
while ((ch = getopt(argc, argv, "a:A:b:c:C:d:f:h:i:lm:M:n:N:p:rv")) > 0) {
while ((ch = getopt(argc, argv, "a:A:b:c:C:d:D:f:h:i:lm:M:n:N:p:rv")) > 0) {
switch (ch) {
case 'a':
action = optarg;
break;
case 'A':
if (rcpt_count >= MAX_RCPT) {
if (add_rcpt_count >= MAX_RCPT) {
fprintf(stderr, "too many -A options\n");
exit(1);
}
rcpt_addr[rcpt_count++] = optarg;
add_rcpt[add_rcpt_count++] = optarg;
break;
case 'b':
#ifdef SMFIR_REPLBODY
@ -572,6 +581,13 @@ int main(int argc, char **argv)
exit(1);
}
break;
case 'D':
if (del_rcpt_count >= MAX_RCPT) {
fprintf(stderr, "too many -D options\n");
exit(1);
}
del_rcpt[del_rcpt_count++] = optarg;
break;
case 'f':
#ifdef SMFIR_CHGFROM
if (chg_from) {

View File

@ -138,8 +138,10 @@ static const char *parse_master_line(PC_MASTER_ENT *masterp, const char *buf)
#define MASTER_BLANKS " \t\r\n" /* XXX */
argv = argv_split(buf, MASTER_BLANKS);
if (argv->argc < PC_MASTER_MIN_FIELDS)
if (argv->argc < PC_MASTER_MIN_FIELDS) {
argv_free(argv); /* Coverity 201311 */
return ("bad field count");
}
normalize_options(argv);
masterp->name_space =
concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0);

View File

@ -39,7 +39,7 @@ update: ../../libexec/$(PROG)
cp $(PROG) ../../libexec
SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o smtpd_xforward.o smtpd_dsn_fix.o \
smtpd_resolve.o smtpd_expand.o
smtpd_resolve.o smtpd_expand.o smtpd_proxy.o smtpd_haproxy.o
smtpd_token: smtpd_token.c $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)

View File

@ -5044,11 +5044,14 @@ int smtpd_input_transp_mask;
char *var_client_checks = "";
char *var_helo_checks = "";
char *var_mail_checks = "";
char *var_relay_checks = "";
char *var_rcpt_checks = "";
char *var_etrn_checks = "";
char *var_data_checks = "";
char *var_eod_checks = "";
char *var_relay_domains = "";
char *var_smtpd_uproxy_proto = "";
int var_smtpd_uproxy_tmout = 0;
#ifdef USE_TLS
char *var_relay_ccerts = "";
@ -5295,6 +5298,7 @@ static const REST_TABLE rest_table[] = {
"client_restrictions", &client_restrctions,
"helo_restrictions", &helo_restrctions,
"sender_restrictions", &mail_restrctions,
"relay_restrictions", &relay_restrctions,
"recipient_restrictions", &rcpt_restrctions,
"etrn_restrictions", &etrn_restrctions,
0,

View File

@ -45,13 +45,13 @@ helo 123.123.123.123
#
sender_restrictions permit_mynetworks,reject_unknown_client
client unknown 131.155.210.17
mail foo@watson.ibm.com
mail foo@ibm.com
client unknown 168.100.189.13
mail foo@watson.ibm.com
mail foo@ibm.com
client foo 123.123.123.123
mail foo@watson.ibm.com
mail foo@ibm.com
sender_restrictions reject_unknown_address
mail foo@watson.ibm.com
mail foo@ibm.com
mail foo@bad.domain
sender_restrictions hash:./smtpd_check_access
mail bad-sender@any.domain
@ -67,18 +67,18 @@ mail foo@friend.bad.domain
#
recipient_restrictions permit_mynetworks,reject_unknown_client,check_relay_domains
client unknown 131.155.210.17
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
client unknown 168.100.189.13
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
client foo 123.123.123.123
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions check_relay_domains
client foo.porcupine.org 168.100.189.13
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
rcpt foo@porcupine.org
client foo 123.123.123.123
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions hash:./smtpd_check_access
mail bad-sender@any.domain
@ -98,7 +98,7 @@ client foo 127.0.0.2
#
recipient_restrictions check_relay_domains
client foo 131.155.210.17
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
client foo 131.155.210.17
rcpt foo@porcupine.org

View File

@ -37,13 +37,13 @@ helo friend.bad.domain
#
sender_restrictions permit_mynetworks,reject_unknown_client
client unknown 131.155.210.17
mail foo@watson.ibm.com
mail foo@ibm.com
client unknown 168.100.189.13
mail foo@watson.ibm.com
mail foo@ibm.com
client foo 123.123.123.123
mail foo@watson.ibm.com
mail foo@ibm.com
sender_restrictions reject_unknown_address
mail foo@watson.ibm.com
mail foo@ibm.com
mail foo@bad.domain
sender_restrictions check_sender_access,hash:./smtpd_check_access
mail bad-sender@any.domain
@ -59,18 +59,18 @@ mail foo@friend.bad.domain
#
recipient_restrictions permit_mynetworks,reject_unknown_client,check_relay_domains
client unknown 131.155.210.17
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
client unknown 168.100.189.13
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
client foo 123.123.123.123
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions check_relay_domains
client foo.porcupine.org 168.100.189.13
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
rcpt foo@porcupine.org
client foo 123.123.123.123
rcpt foo@watson.ibm.com
rcpt foo@ibm.com
rcpt foo@porcupine.org
recipient_restrictions check_recipient_access,hash:./smtpd_check_access
mail bad-sender@any.domain

View File

@ -91,20 +91,20 @@ OK
OK
>>> client unknown 131.155.210.17
OK
>>> mail foo@watson.ibm.com
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
>>> mail foo@ibm.com
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> mail foo@watson.ibm.com
>>> mail foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
>>> mail foo@watson.ibm.com
>>> mail foo@ibm.com
OK
>>> sender_restrictions reject_unknown_address
OK
>>> mail foo@watson.ibm.com
>>> mail foo@ibm.com
OK
>>> mail foo@bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 4.1.8 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain> proto=SMTP helo=<123.123.123.123>
@ -140,34 +140,34 @@ OK
OK
>>> client unknown 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
>>> rcpt foo@ibm.com
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> rcpt foo@watson.ibm.com
>>> rcpt foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
>>> rcpt foo@ibm.com
./smtpd_check: warning: support for restriction "check_relay_domains" will be removed from Postfix; use "reject_unauth_destination" instead
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_relay_domains
OK
>>> client foo.porcupine.org 168.100.189.13
OK
>>> rcpt foo@watson.ibm.com
>>> rcpt foo@ibm.com
OK
>>> rcpt foo@porcupine.org
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@ibm.com
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions hash:./smtpd_check_access
@ -206,9 +206,9 @@ OK
OK
>>> client foo 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<123.123.123.123>
554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@ibm.com
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<123.123.123.123>
554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> client foo 131.155.210.17

View File

@ -71,20 +71,20 @@ OK
OK
>>> client unknown 131.155.210.17
OK
>>> mail foo@watson.ibm.com
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
>>> mail foo@ibm.com
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> mail foo@watson.ibm.com
>>> mail foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
>>> mail foo@watson.ibm.com
>>> mail foo@ibm.com
OK
>>> sender_restrictions reject_unknown_address
OK
>>> mail foo@watson.ibm.com
>>> mail foo@ibm.com
OK
>>> mail foo@bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 4.1.8 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain> proto=SMTP helo=<friend.bad.domain>
@ -120,34 +120,34 @@ OK
OK
>>> client unknown 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
>>> rcpt foo@ibm.com
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
450 4.7.1 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> rcpt foo@watson.ibm.com
>>> rcpt foo@ibm.com
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
>>> rcpt foo@ibm.com
./smtpd_check: warning: support for restriction "check_relay_domains" will be removed from Postfix; use "reject_unauth_destination" instead
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_relay_domains
OK
>>> client foo.porcupine.org 168.100.189.13
OK
>>> rcpt foo@watson.ibm.com
>>> rcpt foo@ibm.com
OK
>>> rcpt foo@porcupine.org
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com> proto=SMTP helo=<friend.bad.domain>
554 5.7.1 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@ibm.com
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@ibm.com> proto=SMTP helo=<friend.bad.domain>
554 5.7.1 <foo@ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_recipient_access,hash:./smtpd_check_access

View File

@ -606,7 +606,10 @@ static void mail_cmd_reset(SINK_STATE *state)
static void ehlo_response(SINK_STATE *state, const char *args)
{
#define SKIP(cp, cond) for (/* void */; *cp && (cond); cp++)
#define SKIP(cp, cond) do { \
for (/* void */; *cp && (cond); cp++) \
/* void */; \
} while (0)
/* EHLO aborts a mail transaction in progress. */
mail_cmd_reset(state);

View File

@ -284,6 +284,10 @@ static int new_server_session_cb(SSL *ssl, SSL_SESSION *session)
/* ticket_cb - configure tls session ticket encrypt/decrypt context */
#if defined(SSL_OP_NO_TICKET) \
&& !defined(OPENSSL_NO_TLSEXT) \
&& OPENSSL_VERSION_NUMBER >= 0x0090808fL
static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
EVP_CIPHER_CTX * ctx, HMAC_CTX * hctx, int create)
{
@ -317,6 +321,8 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
return (TLS_TKT_ACCEPT);
}
#endif
/* tls_server_init - initialize the server-side TLS engine */
TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)

View File

@ -115,7 +115,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
valid_utf_8 ip_match base32_code msg_rate_delay netstring \
vstream
vstream timecmp
LIB_DIR = ../../lib
INC_DIR = ../../include

View File

@ -182,11 +182,21 @@ static DICT *dict_cdbq_open(const char *path, int dict_flags)
char *cdb_path;
int fd;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_CDBQ_OPEN_RETURN(d) { \
DICT *__d = (d); \
myfree(cdb_path); \
return (__d); \
} while (0)
cdb_path = concatenate(path, CDB_SUFFIX, (char *) 0);
if ((fd = open(cdb_path, O_RDONLY)) < 0)
return (dict_surrogate(DICT_TYPE_CDB, path, O_RDONLY, dict_flags,
"open database %s: %m", cdb_path));
DICT_CDBQ_OPEN_RETURN(dict_surrogate(DICT_TYPE_CDB, path,
O_RDONLY, dict_flags,
"open database %s: %m", cdb_path));
dict_cdbq = (DICT_CDBQ *) dict_alloc(DICT_TYPE_CDB,
cdb_path, sizeof(*dict_cdbq));
@ -225,8 +235,7 @@ static DICT *dict_cdbq_open(const char *path, int dict_flags)
if (dict_flags & DICT_FLAG_FOLD_FIX)
dict_cdbq->dict.fold_buf = vstring_alloc(10);
myfree(cdb_path);
return (&dict_cdbq->dict);
DICT_CDBQ_OPEN_RETURN(DICT_DEBUG (&dict_cdbq->dict));
}
/* dict_cdbm_update - add database entry, create mode */
@ -330,6 +339,18 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags)
int fd;
struct stat st0, st1;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_CDBM_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (cdb_path) \
myfree(cdb_path); \
if (tmp_path) \
myfree(tmp_path); \
return (__d); \
} while (0)
cdb_path = concatenate(path, CDB_SUFFIX, (char *) 0);
tmp_path = concatenate(path, CDB_TMP_SUFFIX, (char *) 0);
@ -342,8 +363,10 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags)
*/
for (;;) {
if ((fd = open(tmp_path, O_RDWR | O_CREAT, 0644)) < 0)
return (dict_surrogate(DICT_TYPE_CDB, path, O_RDWR, dict_flags,
"open database %s: %m", tmp_path));
DICT_CDBM_OPEN_RETURN(dict_surrogate(DICT_TYPE_CDB, path,
O_RDWR, dict_flags,
"open database %s: %m",
tmp_path));
if (fstat(fd, &st0) < 0)
msg_fatal("fstat(%s): %m", tmp_path);
@ -383,6 +406,7 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags)
dict_cdbm->dict.update = dict_cdbm_update;
dict_cdbm->cdb_path = cdb_path;
dict_cdbm->tmp_path = tmp_path;
cdb_path = tmp_path = 0; /* DICT_CDBM_OPEN_RETURN() */
dict_cdbm->dict.owner.uid = st1.st_uid;
dict_cdbm->dict.owner.status = (st1.st_uid != 0);
close_on_exec(fd, CLOSE_ON_EXEC);
@ -400,7 +424,7 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags)
if (dict_flags & DICT_FLAG_FOLD_FIX)
dict_cdbm->dict.fold_buf = vstring_alloc(10);
return (&dict_cdbm->dict);
DICT_CDBM_OPEN_RETURN(DICT_DEBUG (&dict_cdbm->dict));
}
/* dict_cdb_open - open data base for query mode or create mode */

View File

@ -165,34 +165,47 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why)
DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_CIDR *dict_cidr;
VSTREAM *map_fp;
VSTREAM *map_fp = 0;
struct stat st;
VSTRING *line_buffer;
VSTRING *why;
VSTRING *line_buffer = 0;
VSTRING *why = 0;
DICT_CIDR_ENTRY *rule;
DICT_CIDR_ENTRY *last_rule = 0;
int lineno = 0;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_CIDR_OPEN_RETURN(d) do { \
DICT *__d = (d); \
if (map_fp != 0 && vstream_fclose(map_fp)) \
msg_fatal("cidr map %s: read error: %m", mapname); \
if (line_buffer != 0) \
vstring_free(line_buffer); \
if (why != 0) \
vstring_free(why); \
return (__d); \
} while (0)
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_CIDR, mapname, open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_CIDR, mapname));
DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_CIDR, mapname));
/*
* Open the configuration file.
*/
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
return (dict_surrogate(DICT_TYPE_CIDR, mapname, open_flags, dict_flags,
"open %s: %m", mapname));
DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname,
open_flags, dict_flags,
"open %s: %m", mapname));
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
/*
* No early returns without memory leaks.
*/
line_buffer = vstring_alloc(100);
why = vstring_alloc(100);
@ -224,13 +237,5 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
last_rule = rule;
}
/*
* Clean up.
*/
if (vstream_fclose(map_fp))
msg_fatal("cidr map %s: read error: %m", mapname);
vstring_free(line_buffer);
vstring_free(why);
return (DICT_DEBUG (&dict_cidr->dict));
DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict));
}

View File

@ -414,9 +414,19 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
DICT_DBM *dict_dbm;
struct stat st;
DBM *dbm;
char *dbm_path;
char *dbm_path = 0;
int lock_fd;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_DBM_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (dbm_path != 0) \
myfree(dbm_path); \
return (__d); \
} while (0)
/*
* Note: DICT_FLAG_LOCK is used only by programs that do fine-grained (in
* the time domain) locking while accessing individual database records.
@ -427,8 +437,10 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
if (dict_flags & DICT_FLAG_LOCK) {
dbm_path = concatenate(path, ".dir", (char *) 0);
if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
return (dict_surrogate(DICT_TYPE_DBM, path, open_flags, dict_flags,
"open database %s: %m", dbm_path));
DICT_DBM_OPEN_RETURN(dict_surrogate(DICT_TYPE_DBM, path,
open_flags, dict_flags,
"open database %s: %m",
dbm_path));
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("shared-lock database %s for open: %m", dbm_path);
}
@ -437,8 +449,10 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
* XXX SunOS 5.x has no const in dbm_open() prototype.
*/
if ((dbm = dbm_open((char *) path, open_flags, 0644)) == 0)
return (dict_surrogate(DICT_TYPE_DBM, path, open_flags, dict_flags,
"open database %s.{dir,pag}: %m", path));
DICT_DBM_OPEN_RETURN(dict_surrogate(DICT_TYPE_DBM, path,
open_flags, dict_flags,
"open database %s.{dir,pag}: %m",
path));
if (dict_flags & DICT_FLAG_LOCK) {
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
@ -483,10 +497,7 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
dict_dbm->key_buf = 0;
dict_dbm->val_buf = 0;
if ((dict_flags & DICT_FLAG_LOCK))
myfree(dbm_path);
return (DICT_DEBUG (&dict_dbm->dict));
DICT_DBM_OPEN_RETURN(DICT_DEBUG (&dict_dbm->dict));
}
#endif

View File

@ -548,6 +548,15 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
int mdb_flags, slmdb_flags, status;
int db_fd;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_LMDB_OPEN_RETURN(d) { \
DICT *__d = (d); \
myfree(mdb_path); \
return (__d); \
} while (0)
mdb_path = concatenate(path, "." DICT_TYPE_LMDB, (char *) 0);
/*
@ -583,12 +592,17 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
* As a workaround the postmap(1) and postalias(1) commands turn on
* MDB_WRITEMAP which disables the use of malloc() in LMDB. However, that
* does not address several disclosures of stack memory. Other Postfix
* databases do not need this workaround: those databases are maintained
* by Postfix daemon processes, and are accessible only by the postfix
* user.
* databases are maintained by Postfix daemon processes, and are
* accessible only by the postfix user.
*
* LMDB 0.9.10 by default does not write uninitialized heap memory to file
* (specify MDB_NOMEMINIT to revert that change). We use the MDB_WRITEMAP
* workaround for older LMDB versions.
*/
#ifndef MDB_NOMEMINIT
if (dict_flags & DICT_FLAG_WORLD_READ)
mdb_flags |= MDB_WRITEMAP;
#endif
/*
* Gracefully handle most database open errors.
@ -599,8 +613,7 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
slmdb_flags)) != 0) {
dict = dict_surrogate(DICT_TYPE_LMDB, path, open_flags, dict_flags,
"open database %s: %s", mdb_path, mdb_strerror(status));
myfree(mdb_path);
return (dict);
DICT_LMDB_OPEN_RETURN(dict);
}
/*
@ -682,9 +695,7 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
*/
dict_lmdb->slmdb = slmdb;
myfree(mdb_path);
return (DICT_DEBUG (&dict_lmdb->dict));
DICT_LMDB_OPEN_RETURN(DICT_DEBUG (&dict_lmdb->dict));
}
#endif

View File

@ -807,29 +807,43 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_PCRE *dict_pcre;
VSTREAM *map_fp;
VSTREAM *map_fp = 0;
struct stat st;
VSTRING *line_buffer;
VSTRING *line_buffer = 0;
DICT_PCRE_RULE *last_rule = 0;
DICT_PCRE_RULE *rule;
int lineno = 0;
int nesting = 0;
char *p;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_PCRE_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (map_fp != 0) \
vstream_fclose(map_fp); \
if (line_buffer != 0) \
vstring_free(line_buffer); \
return (__d); \
} while (0)
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_PCRE, mapname));
DICT_PCRE_OPEN_RETURN(dict_surrogate(DICT_TYPE_PCRE, mapname,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_PCRE, mapname));
/*
* Open the configuration file.
*/
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
return (dict_surrogate(DICT_TYPE_PCRE, mapname, open_flags, dict_flags,
"open %s: %m", mapname));
DICT_PCRE_OPEN_RETURN(dict_surrogate(DICT_TYPE_PCRE, mapname,
open_flags, dict_flags,
"open %s: %m", mapname));
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
@ -880,10 +894,7 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
msg_warn("pcre map %s, line %d: more IFs than ENDIFs",
mapname, lineno);
vstring_free(line_buffer);
vstream_fclose(map_fp);
return (DICT_DEBUG (&dict_pcre->dict));
DICT_PCRE_OPEN_RETURN(DICT_DEBUG (&dict_pcre->dict));
}
#endif /* HAS_PCRE */

View File

@ -738,9 +738,9 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_REGEXP *dict_regexp;
VSTREAM *map_fp;
VSTREAM *map_fp = 0;
struct stat st;
VSTRING *line_buffer;
VSTRING *line_buffer = 0;
DICT_REGEXP_RULE *rule;
DICT_REGEXP_RULE *last_rule = 0;
int lineno = 0;
@ -748,20 +748,34 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
int nesting = 0;
char *p;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_REGEXP_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (line_buffer != 0) \
vstring_free(line_buffer); \
if (map_fp != 0) \
vstream_fclose(map_fp); \
return (__d); \
} while (0)
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_REGEXP, mapname, open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_REGEXP, mapname));
DICT_REGEXP_OPEN_RETURN(dict_surrogate(DICT_TYPE_REGEXP,
mapname, open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_REGEXP, mapname));
/*
* Open the configuration file.
*/
if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0)
return (dict_surrogate(DICT_TYPE_REGEXP, mapname, open_flags, dict_flags,
"open %s: %m", mapname));
DICT_REGEXP_OPEN_RETURN(dict_surrogate(DICT_TYPE_REGEXP, mapname,
open_flags, dict_flags,
"open %s: %m", mapname));
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
@ -818,13 +832,7 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
dict_regexp->pmatch =
(regmatch_t *) mymalloc(sizeof(regmatch_t) * (max_sub + 1));
/*
* Clean up.
*/
vstring_free(line_buffer);
vstream_fclose(map_fp);
return (DICT_DEBUG (&dict_regexp->dict));
DICT_REGEXP_OPEN_RETURN(DICT_DEBUG (&dict_regexp->dict));
}
#endif

View File

@ -309,34 +309,44 @@ static void dict_sockmap_close(DICT *dict)
DICT *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags)
{
DICT_SOCKMAP *dp;
char *saved_name;
char *saved_name = 0;
char *sockmap;
DICT_SOCKMAP_REFC_HANDLE *ref_handle;
HTABLE_INFO *client_info;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_SOCKMAP_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (saved_name != 0) \
myfree(saved_name); \
return (__d); \
} while (0)
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_SOCKMAP, mapname));
DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_SOCKMAP, mapname));
if (dict_flags & DICT_FLAG_NO_UNAUTH)
return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s:%s map is not allowed for security-sensitive data",
DICT_TYPE_SOCKMAP, mapname));
DICT_TYPE_SOCKMAP, mapname));
/*
* Separate the socketmap name from the socketmap server name.
*/
saved_name = mystrdup(mapname);
if ((sockmap = split_at_right(saved_name, ':')) == 0)
return (dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s requires server:socketmap argument",
DICT_TYPE_SOCKMAP));
DICT_SOCKMAP_OPEN_RETURN(dict_surrogate(DICT_TYPE_SOCKMAP, mapname,
open_flags, dict_flags,
"%s requires server:socketmap argument",
DICT_TYPE_SOCKMAP));
/*
* Use one reference-counted client handle for all socketmaps with the
@ -370,10 +380,5 @@ DICT *dict_sockmap_open(const char *mapname, int open_flags, int dict_flags)
/* Don't look up parent domains or network superblocks. */
dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
/*
* Clean up.
*/
myfree(saved_name);
return (DICT_DEBUG (&dp->dict));
DICT_SOCKMAP_OPEN_RETURN(DICT_DEBUG (&dp->dict));
}

View File

@ -145,7 +145,7 @@ static void dict_thash_close(DICT *dict)
DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
{
DICT_THASH *dict_thash;
VSTREAM *fp;
VSTREAM *fp = 0;
struct stat st;
time_t before;
time_t after;
@ -156,13 +156,26 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
HTABLE *table;
HTABLE_INFO *ht;
/*
* Let the optimizer worry about eliminating redundant code.
*/
#define DICT_THASH_OPEN_RETURN(d) { \
DICT *__d = (d); \
if (fp != 0) \
vstream_fclose(fp); \
if (line_buffer != 0) \
vstring_free(line_buffer); \
return (__d); \
} while (0)
/*
* Sanity checks.
*/
if (open_flags != O_RDONLY)
return (dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_THASH, path));
DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path,
open_flags, dict_flags,
"%s:%s map requires O_RDONLY access mode",
DICT_TYPE_THASH, path));
/*
* Read the flat text file into in-memory hash. Read the file again if it
@ -170,8 +183,9 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
*/
for (before = time((time_t *) 0); /* see below */ ; before = after) {
if ((fp = vstream_fopen(path, open_flags, 0644)) == 0) {
return (dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags,
"open database %s: %m", path));
DICT_THASH_OPEN_RETURN(dict_surrogate(DICT_TYPE_THASH, path,
open_flags, dict_flags,
"open database %s: %m", path));
}
if (line_buffer == 0)
line_buffer = vstring_alloc(100);
@ -240,6 +254,7 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
msg_fatal("fstat %s: %m", path);
if (vstream_fclose(fp))
msg_fatal("read %s: %m", path);
fp = 0; /* DICT_THASH_OPEN_RETURN() */
after = time((time_t *) 0);
if (st.st_mtime < before - 1 || st.st_mtime > after)
break;
@ -252,7 +267,6 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
msg_info("pausing to let file %s cool down", path);
doze(300000);
}
vstring_free(line_buffer);
/*
* Create the in-memory table.
@ -270,5 +284,5 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
dict_thash->dict.owner.uid = st.st_uid;
dict_thash->dict.owner.status = (st.st_uid != 0);
return (DICT_DEBUG (&dict_thash->dict));
DICT_THASH_OPEN_RETURN(DICT_DEBUG (&dict_thash->dict));
}

View File

@ -94,8 +94,10 @@ int mac_parse(const char *value, MAC_PARSE_FN action, char *context)
int level;
int status = 0;
#define SKIP(start, var, cond) \
for (var = start; *var && (cond); var++);
#define SKIP(start, var, cond) do { \
for (var = start; *var && (cond); var++) \
/* void */; \
} while (0)
if (msg_verbose > 1)
msg_info("%s: %s", myname, value);

View File

@ -68,14 +68,17 @@ const char *split_nameval(char *buf, char **name, char **value)
/*
* Ugly macros to make complex expressions less unreadable.
*/
#define SKIP(start, var, cond) \
for (var = start; *var && (cond); var++);
#define SKIP(start, var, cond) do { \
for (var = start; *var && (cond); var++) \
/* void */; \
} while (0)
#define TRIM(s) { \
#define TRIM(s) do { \
char *p; \
for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \
for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
/* void */; \
*p = 0; \
}
} while (0)
SKIP(buf, np, ISSPACE(*np)); /* find name begin */
if (*np == 0)

View File

@ -125,6 +125,7 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap)
unsigned long_flag; /* long or plain integer */
int ch;
char *s;
int saved_errno = errno; /* VBUF_SPACE() may clobber it */
/*
* Assume that format strings are short.
@ -241,7 +242,7 @@ VBUF *vbuf_print(VBUF *bp, const char *format, va_list ap)
VBUF_SKIP(bp);
break;
case 'm':
VBUF_STRCAT(bp, strerror(errno));
VBUF_STRCAT(bp, strerror(saved_errno));
break;
case 'p':
if (VBUF_SPACE(bp, (width > prec ? width : prec) + PTR_SPACE))