2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 21:27:57 +00:00

postfix-2.12-20141013

This commit is contained in:
Wietse Venema 2014-10-13 00:00:00 -05:00 committed by Viktor Dukhovni
parent 757df5bc6c
commit 783583def2
25 changed files with 324 additions and 96 deletions

View File

@ -20640,3 +20640,25 @@ Apologies for any names omitted.
./proto/postconf.proto, global/mail_params.h, smtp/lmtp_params.c,
smtp/smtp.c, smtp/smtp.h, smtp/smtp_connect.c, smtp/smtp_params.c,
smtp/smtp_proto.c, smtp/smtp_tls_policy.c, smtp/smtp_trouble.c.
20141012
Cleanup: missing format-string checks. Files: master/master_ent.c,
posttls-finger/posttls-finger.c, smtpd/smtpd_proxy.c.
Bugfix: the PREPEND access/policy action added headers ABOVE
Postfix's own Received: header, exposing Postfix's own
Received: header to Milters (protocol violation) and hiding
the PREPENDed header from Milters. The latter caused problems
for DMARC implementations with SPF policy plus DKIM Milter.
PREPENDed headers are now added BELOW Postfix's own Received:
header and remain visible to Milters. File: smtpd/smtpd.c.
20141013
Cleanup: configuration file line numbers in error/warning
messages could point to comment lines before or after the
problem. Files: util/readlline.[hc], master/master_ent.c,
postalias/postalias.c, postmap/postmap.c, util/dict.c,
util/dict_cidr.c, util/dict_pcre.e, util/dict_regexp.c,
util/dict_thash.c, postconf/postconf_master.c.

View File

@ -1027,8 +1027,11 @@ default. This is the recommended configuration for early adopters.
* The "example.com" destination uses DANE, but if TLSA records are not
present or are unusable, mail is deferred.
* The "example.org" destination uses DANE if possible, but if no TLSA records
are found opportunistic TLS is used.
* The "example.org" destination uses DANE if possible, but uses opportunistic
TLS if no TLSA records are found. The "fallback" attribute (Postfix >=
2.12) overrides the global main.cf smtp_tls_fallback_level parameter to
employ unauthenticated mandatory encryption if DANE authentication fails,
after logging a warning.
main.cf:
indexed = ${default_database_type}:${config_directory}/
@ -1052,6 +1055,8 @@ default. This is the recommended configuration for early adopters.
tls_policy:
example.com dane-only
# Postfix >= 2.12, per-destination smtp_tls_fallback_level override
example.org dane fallback=encrypt
master.cf:
dane unix - - n - - smtp
@ -1632,7 +1637,9 @@ ddaannee
obtained for the remote SMTP server, SSLv2 is automatically disabled (see
smtp_tls_mandatory_protocols), and the server certificate must match the
TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
available with Postfix 2.11 and later.
available with Postfix 2.11 and later. The optional "fallback" attribute
provides a per-site override of the main.cf smtp_tls_fallback_level
parameter (Postfix >= 2.12).
ddaannee--oonnllyy
Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA
records in DNSSEC. If no TLSA records are found, or none are usable, no
@ -1640,7 +1647,9 @@ ddaannee--oonnllyy
the remote SMTP server, SSLv2 is automatically disabled (see
smtp_tls_mandatory_protocols), and the server certificate must match the
TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
available with Postfix 2.11 and later.
available with Postfix 2.11 and later. The optional "fallback" attribute
provides a per-site override of the main.cf smtp_tls_fallback_level
parameter (Postfix >= 2.12).
ffiinnggeerrpprriinntt
Certificate fingerprint verification. Available with Postfix 2.5 and later.
At this security level, there are no trusted certificate authorities. The
@ -1653,7 +1662,8 @@ ffiinnggeerrpprriinntt
combined with a "|" delimiter in a single match attribute, or multiple
match attributes can be employed. The ":" character is not used as a
delimiter as it occurs between each pair of fingerprint (hexadecimal)
digits.
digits. The optional "fallback" attribute provides a per-site override of
the main.cf smtp_tls_fallback_level parameter (Postfix >= 2.12).
vveerriiffyy
Mandatory server certificate verification. Mail is delivered only if the
TLS handshake succeeds, if the remote SMTP server certificate can be
@ -1664,7 +1674,8 @@ vveerriiffyy
"tafile" attribute optionally modifies trust chain verification in the same
manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
attribute may be specified multiple times to load multiple trust-anchor
files.
files. The optional "fallback" attribute provides a per-site override of
the main.cf smtp_tls_fallback_level parameter (Postfix >= 2.12).
sseeccuurree
Secure certificate verification. Mail is delivered only if the TLS
handshake succeeds, if the remote SMTP server certificate can be validated
@ -1674,7 +1685,9 @@ sseeccuurree
"match" attribute is specified). With Postfix >= 2.11 the "tafile"
attribute optionally modifies trust chain verification in the same manner
as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may
be specified multiple times to load multiple trust-anchor files.
be specified multiple times to load multiple trust-anchor files. The
optional "fallback" attribute provides a per-site override of the main.cf
smtp_tls_fallback_level parameter (Postfix >= 2.12).
Notes:
* The "match" attribute is especially useful to verify TLS certificates for
@ -1708,6 +1721,7 @@ Example:
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
# Postfix 2.5 and later
smtp_tls_fingerprint_digest = md5
/etc/postfix/tls_policy:
example.edu none
example.mil may
@ -1723,6 +1737,8 @@ Example:
# Postfix 2.6 and later
example.info may protocols=!SSLv2 ciphers=medium
exclude=3DES
# Postfix 2.12 and later override of smtp_tls_fallback_level
fallback.example secure fallback=encrypt
NNoottee:: The "hostname" strategy if listed in a non-default setting of
smtp_tls_secure_cert_match or in the "match" attribute in the policy table can

View File

@ -59,6 +59,16 @@ Maintainers may also benefit from the makedefs documentation
(mantools/srctoman - makedefs | nroff -man | less) with information
about build options that are not described in the INSTALL instructions.
Incompatible changes with snapshot 20141013
===========================================
Headers prepended with the access/policy PREPEND action are now
added BELOW Postfix's own Recived: header. This ensures a) that
Postfix's own Recived: header remains hidden from Milters as required
by the Milter protocol, and b) that PREPENDed headers become visible
to Milters, as expected by DMARC implementations based on SPF policy
plus DKIM milter.
Major changes with snapshot 20141011
====================================
@ -73,7 +83,7 @@ Fallback to unauthenticated TLS is logged, so that downgrade attacks
are "tamper-evident". Fallback should be used only when testing,
or temporarily when working around a known problem at a remote site.
Incompatible changes with snapshot 20141008
Incompatible changes with snapshot 20141009
===========================================
The default settings have changed for relay_domains (new: empty,

View File

@ -1373,8 +1373,12 @@ for early adopters. <p>
<li> <p> The "example.com" destination uses DANE, but if TLSA records
are not present or are unusable, mail is deferred. </p>
<li> <p> The "example.org" destination uses DANE if possible, but if no TLSA
records are found opportunistic TLS is used. </p>
<li> <p> The "example.org" destination uses DANE if possible, but
uses opportunistic TLS if no TLSA records are found. The
"fallback" attribute (Postfix &ge; 2.12) overrides the global
<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter to employ unauthenticated
mandatory encryption if DANE authentication fails, after logging a
warning. </p>
</ul>
<blockquote>
@ -1394,26 +1398,16 @@ records are found opportunistic TLS is used. </p>
# <a href="postconf.5.html#default_transport">default_transport</a> = smtp, but some destinations are special:
#
<a href="postconf.5.html#transport_maps">transport_maps</a> = ${indexed}transport
</pre>
</blockquote>
<blockquote>
<pre>
transport:
example.com dane
example.org dane
</pre>
</blockquote>
<blockquote>
<pre>
tls_policy:
example.com dane-only
</pre>
</blockquote>
# Postfix &ge; 2.12, per-destination <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> override
example.org dane fallback=encrypt
<blockquote>
<pre>
<a href="master.5.html">master.cf</a>:
dane unix - - n - - smtp
-o <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a>=dnssec
@ -2146,7 +2140,10 @@ href="#client_tls_encrypt">encrypt</a>. When usable TLSA records
are obtained for the remote SMTP server, SSLv2 is automatically
disabled (see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate
must match the TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication
and DNSSEC support is available with Postfix 2.11 and later. </dd>
and DNSSEC support is available with Postfix 2.11 and later.
The optional "fallback" attribute provides a per-site override of
the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
</dd>
<dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
@ -2155,7 +2152,10 @@ connection is made to the server. When usable TLSA records are
obtained for the remote SMTP server, SSLv2 is automatically disabled
(see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate must
match the TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication and
DNSSEC support is available with Postfix 2.11 and later. </dd>
DNSSEC support is available with Postfix 2.11 and later.
The optional "fallback" attribute provides a per-site override of
the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
</dd>
<dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
fingerprint verification.</a> Available with Postfix 2.5 and
@ -2164,13 +2164,15 @@ authorities. The certificate trust chain, expiration date, ... are
not checked. Instead, the optional <b>match</b> attribute, or else
the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a></b> parameter, lists
the server certificate fingerprints or public key fingerprints
(Postfix 2.9 and later). The
digest algorithm used to calculate fingerprints is selected by the
<b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b> parameter. Multiple fingerprints can
be combined with a "|" delimiter in a single match attribute, or multiple
match attributes can be employed. The ":" character is not used as a
delimiter as it occurs between each pair of fingerprint (hexadecimal)
digits. </dd>
(Postfix 2.9 and later). The digest algorithm used to calculate
fingerprints is selected by the <b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b>
parameter. Multiple fingerprints can be combined with a "|" delimiter
in a single match attribute, or multiple match attributes can be
employed. The ":" character is not used as a delimiter as it occurs
between each pair of fingerprint (hexadecimal) digits.
The optional "fallback" attribute provides a per-site override of
the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
</dd>
<dt><b>verify</b></dt> <dd><a href="#client_tls_verify">Mandatory
server certificate verification</a>. Mail is delivered only if the
@ -2181,9 +2183,11 @@ the optional "match" attribute (or the <a href="postconf.5.html">main.cf</a> <a
parameter value when no optional "match" attribute is specified).
With Postfix &ge; 2.11 the "tafile" attribute optionally modifies
trust chain verification in the same manner as the
"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute
may be specified multiple times to load multiple trust-anchor
files. </dd>
"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute may
be specified multiple times to load multiple trust-anchor files.
The optional "fallback" attribute provides a per-site override of
the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
</dd>
<dt><b>secure</b></dt> <dd><a href="#client_tls_secure">Secure certificate
verification.</a> Mail is delivered only if the TLS handshake succeeds,
@ -2195,7 +2199,10 @@ server certificate name matches the optional "match" attribute (or the
attribute optionally modifies trust chain verification in the same manner
as the "<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute
may be specified multiple times to load multiple trust-anchor
files. </dd>
files.
The optional "fallback" attribute provides a per-site override of
the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
</dd>
</dl>
@ -2242,6 +2249,7 @@ Example:
<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/tls_policy
# Postfix 2.5 and later
<a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a> = md5
/etc/postfix/tls_policy:
example.edu none
example.mil may
@ -2256,6 +2264,8 @@ Example:
match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1
# Postfix 2.6 and later
example.info may protocols=!SSLv2 ciphers=medium exclude=3DES
# Postfix 2.12 and later override of <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a>
fallback.example secure fallback=encrypt
</pre>
</blockquote>

View File

@ -552,6 +552,11 @@ SMTP(8) SMTP(8)
<b><a href="postconf.5.html#tlsmgr_service_name">tlsmgr_service_name</a> (tlsmgr)</b>
The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
Available in Postfix version 2.12 and later:
<b><a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> (empty)</b>
Optional fallback levels for authenticated TLS levels.
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compatibility with
Postfix versions before 2.3. Support for these will be removed in a

View File

@ -5027,6 +5027,17 @@ configuration parameter. See there for details. </p>
<p> This feature is available in Postfix 2.3 and later. </p>
</DD>
<DT><b><a name="lmtp_tls_fallback_level">lmtp_tls_fallback_level</a>
(default: empty)</b></DT><DD>
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a>
configuration parameter. See there for details. </p>
<p> This feature is available in Postfix 2.12 and later. </p>
</DD>
<DT><b><a name="lmtp_tls_fingerprint_cert_match">lmtp_tls_fingerprint_cert_match</a>
@ -11637,6 +11648,61 @@ key exchange with RSA authentication. </p>
<p> This feature is available in Postfix 2.3 and later. </p>
</DD>
<DT><b><a name="smtp_tls_fallback_level">smtp_tls_fallback_level</a>
(default: empty)</b></DT><DD>
<p> Optional fallback levels for authenticated TLS levels. Specify
a white-space or comma-separated list of
<b>policy_level</b>=<b>fallback_level</b> pairs. The <b>policy_level</b>
must require authentication (one of dane, dane-only, fingerprint,
verify, secure). The <b>fallback_level</b> must be "encrypt" or
"may". When an authenticated connection at some desired policy
level cannot be established, delivery will proceed at the correponding
fallback level if possible. A warning will be logged
indicating the fallback reason. </p>
<p> The TLS <a href="TLS_README.html#client_tls_policy">policy</a> table
can be used to specify a destination-specific fallback strategy via the
"fallback" policy attribute. The value of the "fallback" attribute, if
specified, must be "may", "encrypt" or "none". If not "none", this
specifies the fallback level for the destination in question. If the
attribute value is "none", fallback is suppressed for the destination
even if enabled via a global setting of <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a>. </p>
<p> Example: </p>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
# When authentication fails, log a warning and deliver anyway
# over an unauthenticated TLS connection.
#
<a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> =
dane=encrypt,
dane-only=encrypt,
fingerprint=encrypt,
verify=encrypt,
secure=encrypt
indexed = ${<a href="postconf.5.html#default_database_type">default_database_type</a>}:${<a href="postconf.5.html#config_directory">config_directory</a>}/
<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = ${indexed}tls-policy
</pre>
</blockquote>
<blockquote>
<pre>
/etc/postfix/tls-policy:
# No fallback for example.com
example.com secure fallback=none
# For example.net tolerate cleartext fallback
example.net dane fallback=may
</pre>
</blockquote>
<p> This feature is available in Postfix 2.12 and later. </p>
</DD>
<DT><b><a name="smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a>

View File

@ -552,6 +552,11 @@ SMTP(8) SMTP(8)
<b><a href="postconf.5.html#tlsmgr_service_name">tlsmgr_service_name</a> (tlsmgr)</b>
The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
Available in Postfix version 2.12 and later:
<b><a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> (empty)</b>
Optional fallback levels for authenticated TLS levels.
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compatibility with
Postfix versions before 2.3. Support for these will be removed in a

View File

@ -2970,6 +2970,11 @@ The LMTP-specific version of the smtp_tls_exclude_ciphers
configuration parameter. See there for details.
.PP
This feature is available in Postfix 2.3 and later.
.SH lmtp_tls_fallback_level (default: empty)
The LMTP-specific version of the smtp_tls_fallback_level
configuration parameter. See there for details.
.PP
This feature is available in Postfix 2.12 and later.
.SH lmtp_tls_fingerprint_cert_match (default: empty)
The LMTP-specific version of the smtp_tls_fingerprint_cert_match
configuration parameter. See there for details.
@ -7304,6 +7309,63 @@ and "DES-CBC3-MD5". The last setting disables ciphers that use "EDH"
key exchange with RSA authentication.
.PP
This feature is available in Postfix 2.3 and later.
.SH smtp_tls_fallback_level (default: empty)
Optional fallback levels for authenticated TLS levels. Specify
a white-space or comma-separated list of
\fBpolicy_level\fR=\fBfallback_level\fR pairs. The \fBpolicy_level\fR
must require authentication (one of dane, dane-only, fingerprint,
verify, secure). The \fBfallback_level\fR must be "encrypt" or
"may". When an authenticated connection at some desired policy
level cannot be established, delivery will proceed at the correponding
fallback level if possible. A warning will be logged
indicating the fallback reason.
.PP
The TLS policy table
can be used to specify a destination-specific fallback strategy via the
"fallback" policy attribute. The value of the "fallback" attribute, if
specified, must be "may", "encrypt" or "none". If not "none", this
specifies the fallback level for the destination in question. If the
attribute value is "none", fallback is suppressed for the destination
even if enabled via a global setting of smtp_tls_fallback_level.
.PP
Example:
.sp
.in +4
.nf
.na
.ft C
/etc/postfix/main.cf:
# When authentication fails, log a warning and deliver anyway
# over an unauthenticated TLS connection.
#
smtp_tls_fallback_level =
dane=encrypt,
dane-only=encrypt,
fingerprint=encrypt,
verify=encrypt,
secure=encrypt
indexed = ${default_database_type}:${config_directory}/
smtp_tls_policy_maps = ${indexed}tls-policy
.fi
.ad
.ft R
.in -4
.sp
.in +4
.nf
.na
.ft C
/etc/postfix/tls-policy:
# No fallback for example.com
example.com secure fallback=none
# For example.net tolerate cleartext fallback
example.net dane fallback=may
.fi
.ad
.ft R
.in -4
.PP
This feature is available in Postfix 2.12 and later.
.SH smtp_tls_fingerprint_cert_match (default: empty)
List of acceptable remote SMTP server certificate fingerprints for
the "fingerprint" TLS security level (\fBsmtp_tls_security_level\fR =

View File

@ -492,6 +492,10 @@ not an alias and its address records lie in an unsigned zone.
RFC 6698 trust-anchor digest support in the Postfix TLS library.
.IP "\fBtlsmgr_service_name (tlsmgr)\fR"
The name of the \fBtlsmgr\fR(8) service entry in master.cf.
.PP
Available in Postfix version 2.12 and later:
.IP "\fBsmtp_tls_fallback_level (empty)\fR"
Optional fallback levels for authenticated TLS levels.
.SH "OBSOLETE STARTTLS CONTROLS"
.na
.nf

View File

@ -7,13 +7,13 @@
/* #include <mail_parm_split.h>
/*
/* ARGV *mail_parm_split(
/* cost char *name,
/* const char *name,
/* const char *value)
/* DESCRIPTION
/* mail_parm_split() splits a parameter list value into its
/* elements, and extracts text from inside {}. It uses
/* CHARS_COMMA_SP as list element delimiters, and CHARS_BRACE
/* for grouping.
/* elements, and extracts text from elements that are entirely
/* enclosed in {}. It uses CHARS_COMMA_SP as list element
/* delimiters, and CHARS_BRACE for grouping.
/*
/* Arguments:
/* .IP name
@ -22,7 +22,8 @@
/* .IP value
/* Parameter value.
/* DIAGNOSTICS
/* fatal: syntax error while extracting text from {}.
/* fatal: syntax error while extracting text from {}, such as:
/* missing closing brace, or text after closing brace.
/* SEE ALSO
/* argv_splitq(3), string array utilities
/* extpar(3), extract text from parentheses

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 "20141011"
#define MAIL_RELEASE_DATE "20141013"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT

View File

@ -106,13 +106,11 @@
static char *master_path; /* config file name */
static VSTREAM *master_fp; /* config file pointer */
static int master_line; /* config file line number */
static int master_line_first; /* config file line number */
static ARGV *master_disable; /* disabled service patterns */
static char master_blanks[] = " \t\r\n";/* field delimiters */
static NORETURN fatal_invalid_field(char *, char *);
static NORETURN fatal_with_context(char *,...);
/* fset_master_ent - specify configuration file pathname */
void fset_master_ent(char *path)
@ -167,9 +165,21 @@ void end_master_ent()
master_disable = 0;
}
/* master_conf_context - plot the target range */
static const char *master_conf_context(void)
{
static VSTRING *context_buf = 0;
if (context_buf == 0)
context_buf = vstring_alloc(100);
vstring_sprintf(context_buf, "%s: line %d", master_path, master_line_first);
return (vstring_str(context_buf));
}
/* fatal_with_context - print fatal error with file/line context */
static NORETURN fatal_with_context(char *format,...)
static NORETURN PRINTFLIKE(1, 2) fatal_with_context(char *format,...)
{
const char *myname = "fatal_with_context";
VSTRING *vp = vstring_alloc(100);
@ -181,7 +191,7 @@ static NORETURN fatal_with_context(char *format,...)
va_start(ap, format);
vstring_vsprintf(vp, format, ap);
va_end(ap);
msg_fatal("%s: line %d: %s", master_path, master_line, vstring_str(vp));
msg_fatal("%s: %s", master_conf_context(), vstring_str(vp));
}
/* fatal_invalid_field - report invalid field value */
@ -203,8 +213,8 @@ static char *get_str_ent(char **bufp, char *name, char *def_val)
if (def_val == 0)
fatal_with_context("field \"%s\" has no default value", name);
if (warn_compat_break_chroot && strcmp(name, "chroot") == 0)
msg_info("%s: line %d: using backwards-compatible default setting "
"%s=%s", master_path, master_line, name, def_val);
msg_info("%s: using backwards-compatible default setting "
"%s=%s", master_conf_context(), name, def_val);
return (def_val);
} else {
return (value);
@ -288,7 +298,7 @@ MASTER_SERV *get_master_ent()
* Skip blank lines and comment lines.
*/
for (;;) {
if (readlline(buf, master_fp, &master_line) == 0) {
if (readllines(buf, master_fp, &master_line, &master_line_first) == 0) {
vstring_free(buf);
vstring_free(junk);
return (0);
@ -340,17 +350,14 @@ MASTER_SERV *get_master_ent()
serv->type = MASTER_SERV_TYPE_INET;
atmp = mystrdup(name);
if ((parse_err = host_port(atmp, &host, "", &port, (char *) 0)) != 0)
msg_fatal("%s: line %d: %s in \"%s\"",
VSTREAM_PATH(master_fp), master_line,
parse_err, name);
fatal_with_context("%s in \"%s\"", parse_err, name);
if (*host) {
serv->flags |= MASTER_FLAG_INETHOST;/* host:port */
MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
msg_fatal("%s: line %d: bad hostname or network address: %s",
VSTREAM_PATH(master_fp), master_line, name);
fatal_with_context("bad hostname or network address: %s", name);
inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
} else {
@ -454,8 +461,7 @@ MASTER_SERV *get_master_ent()
* sockets is frozen anyway once we build the command-line vector below.
*/
if (serv->listen_fd_count == 0) {
msg_fatal("%s: line %d: no valid IP address found: %s",
VSTREAM_PATH(master_fp), master_line, name);
fatal_with_context("no valid IP address found: %s", name);
}
serv->listen_fd = (int *) mymalloc(sizeof(int) * serv->listen_fd_count);
for (n = 0; n < serv->listen_fd_count; n++)
@ -557,8 +563,7 @@ MASTER_SERV *get_master_ent()
(char *) 0);
while ((cp = mystrtokq(&bufp, master_blanks, "{}")) != 0) {
if (*cp == '{' && (err = extpar(&cp, "{}", EXTPAR_FLAG_STRIP)) != 0)
msg_fatal("%s: line %d: %s",
VSTREAM_PATH(master_fp), master_line, err);
fatal_with_context("%s", err);
argv_add(serv->args, cp, (char *) 0);
}
argv_terminate(serv->args);

View File

@ -263,6 +263,7 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
VSTRING *line_buffer;
MKMAP *mkmap;
int lineno;
int last_line;
VSTRING *key_buffer;
VSTRING *value_buffer;
TOK822 *tok_list;
@ -334,8 +335,8 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
/*
* Add records to the database.
*/
lineno = 0;
while (readlline(line_buffer, source_fp, &lineno)) {
last_line = 0;
while (readllines(line_buffer, source_fp, &last_line, &lineno)) {
/*
* Tokenize the input, so that we do the right thing when a

View File

@ -395,7 +395,8 @@ void pcf_read_master(int fail_on_open_error)
VSTREAM *fp;
const char *err;
int entry_count = 0;
int line_count = 0;
int line_count;
int last_line = 0;
/*
* Sanity check.
@ -425,7 +426,7 @@ void pcf_read_master(int fail_on_open_error)
msg_warn("open %s: %m", path);
} else {
buf = vstring_alloc(100);
while (readlline(buf, fp, &line_count) != 0) {
while (readllines(buf, fp, &last_line, &line_count) != 0) {
pcf_master_table = (PCF_MASTER_ENT *) myrealloc((char *) pcf_master_table,
(entry_count + 2) * sizeof(*pcf_master_table));
if ((err = pcf_parse_master_entry(pcf_master_table + entry_count,

View File

@ -332,6 +332,7 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
VSTRING *line_buffer;
MKMAP *mkmap;
int lineno;
int last_line;
char *key;
char *value;
struct stat st;
@ -397,8 +398,8 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
/*
* Add records to the database.
*/
lineno = 0;
while (readlline(line_buffer, source_fp, &lineno)) {
last_line = 0;
while (readllines(line_buffer, source_fp, &last_line, &lineno)) {
/*
* Split on the first whitespace character, then trim leading and

View File

@ -453,7 +453,7 @@ typedef struct { /* server response */
/* command - send an SMTP command */
static void command(STATE *state, int verbose, char *fmt,...)
static void PRINTFLIKE(3, 4) command(STATE *state, int verbose, char *fmt,...)
{
VSTREAM *stream = state->stream;
VSTRING *buf;

View File

@ -3114,13 +3114,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
}
/*
* PREPEND message headers.
*/
if (state->prepend)
for (cpp = state->prepend->argv; *cpp; cpp++)
out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
/*
* Suppress our own Received: header in the unlikely case that we are an
* intermediate proxy.
@ -3210,6 +3203,14 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
"\t(envelope-from %s)", STR(state->buffer));
#endif
}
/*
* PREPEND message headers.
*/
if (state->prepend)
for (cpp = state->prepend->argv; *cpp; cpp++)
out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
state->where = SMTPD_AFTER_DATA;

View File

@ -233,7 +233,7 @@ static VSTREAM *smtpd_proxy_replay_stream;
*/
static void smtpd_proxy_fake_server_reply(SMTPD_STATE *, int);
static int smtpd_proxy_rdwr_error(SMTPD_STATE *, int);
static int smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
static int PRINTFLIKE(3, 4) smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
static int smtpd_proxy_rec_put(VSTREAM *, int, const char *, ssize_t);
/*
@ -652,7 +652,7 @@ static int smtpd_proxy_replay_send(SMTPD_STATE *state)
/* smtpd_proxy_save_cmd - save SMTP command + expected response to replay log */
static int smtpd_proxy_save_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
static int PRINTFLIKE(3, 4) smtpd_proxy_save_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
{
va_list ap;

View File

@ -476,7 +476,7 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp)
char *member;
char *val;
const char *old;
int old_lineno;
int last_line;
int lineno;
const char *err;
struct stat st;
@ -487,16 +487,15 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp)
*/
DICT_FIND_FOR_UPDATE(dict, dict_name);
buf = vstring_alloc(100);
old_lineno = lineno = 0;
last_line = 0;
if (fstat(vstream_fileno(fp), &st) < 0)
msg_fatal("fstat %s: %m", VSTREAM_PATH(fp));
for ( /* void */ ; readlline(buf, fp, &lineno); old_lineno = lineno) {
while (readllines(buf, fp, &last_line, &lineno)) {
if ((err = split_nameval(STR(buf), &member, &val)) != 0)
msg_fatal("%s, line %s: %s: \"%s\"",
msg_fatal("%s, line %d: %s: \"%s\"",
VSTREAM_PATH(fp),
format_line_number((VSTRING *) 0,
old_lineno + 1, lineno),
lineno,
err, STR(buf));
if (msg_verbose > 1)
msg_info("%s: %s = %s", myname, member, val);

View File

@ -171,7 +171,8 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
VSTRING *why = 0;
DICT_CIDR_ENTRY *rule;
DICT_CIDR_ENTRY *last_rule = 0;
int lineno = 0;
int last_line = 0;
int lineno;
/*
* Let the optimizer worry about eliminating redundant code.
@ -223,7 +224,7 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
dict_cidr->dict.owner.uid = st.st_uid;
dict_cidr->dict.owner.status = (st.st_uid != 0);
while (readlline(line_buffer, map_fp, &lineno)) {
while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
rule = dict_cidr_parse_rule(vstring_str(line_buffer), why);
if (rule == 0) {
msg_warn("cidr map %s, line %d: %s: skipping this rule",

View File

@ -812,7 +812,8 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
VSTRING *line_buffer = 0;
DICT_PCRE_RULE *last_rule = 0;
DICT_PCRE_RULE *rule;
int lineno = 0;
int last_line = 0;
int lineno;
int nesting = 0;
char *p;
@ -870,7 +871,7 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
/*
* Parse the pcre table.
*/
while (readlline(line_buffer, map_fp, &lineno)) {
while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
p = vstring_str(line_buffer);
trimblanks(p, 0)[0] = 0; /* Trim space at end */
if (*p == 0)

View File

@ -743,7 +743,8 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
VSTRING *line_buffer = 0;
DICT_REGEXP_RULE *rule;
DICT_REGEXP_RULE *last_rule = 0;
int lineno = 0;
int lineno;
int last_line = 0;
size_t max_sub = 0;
int nesting = 0;
char *p;
@ -797,7 +798,7 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
/*
* Parse the regexp table.
*/
while (readlline(line_buffer, map_fp, &lineno)) {
while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
p = vstring_str(line_buffer);
trimblanks(p, 0)[0] = 0;
if (*p == 0)

View File

@ -151,6 +151,7 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
time_t after;
VSTRING *line_buffer = 0;
int lineno;
int last_line;
char *key;
char *value;
HTABLE *table;
@ -189,9 +190,9 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
}
if (line_buffer == 0)
line_buffer = vstring_alloc(100);
lineno = 0;
last_line = 0;
table = htable_create(13);
while (readlline(line_buffer, fp, &lineno)) {
while (readllines(line_buffer, fp, &last_line, &lineno)) {
/*
* Split on the first whitespace character, then trim leading and

View File

@ -6,12 +6,18 @@
/* SYNOPSIS
/* #include <readlline.h>
/*
/* VSTRING *readllines(buf, fp, lineno, first_line)
/* VSTRING *buf;
/* VSTREAM *fp;
/* int *lineno;
/* int *first_line;
/*
/* VSTRING *readlline(buf, fp, lineno)
/* VSTRING *buf;
/* VSTREAM *fp;
/* int *lineno;
/* DESCRIPTION
/* readlline() reads one logical line from the named stream.
/* readllines() reads one logical line from the named stream.
/* .IP "blank lines and comments"
/* Empty lines and whitespace-only lines are ignored, as
/* are lines whose first non-whitespace character is a `#'.
@ -22,6 +28,8 @@
/* The result value is the input buffer argument or a null pointer
/* when no input is found.
/*
/* readlline() is a backwards-compatibility wrapper.
/*
/* Arguments:
/* .IP buf
/* A variable-length buffer for input. The result is null terminated.
@ -29,8 +37,11 @@
/* Handle to an open stream.
/* .IP lineno
/* A null pointer, or a pointer to an integer that is incremented
/* after reading a newline character.
/* .RE
/* after reading a physical line.
/* .IP first_line
/* A null pointer, or a pointer to an integer that will contain
/* the line number of the first non-blank, non-comment line
/* in the result logical line.
/* DIAGNOSTICS
/* Warning: a continuation line that does not continue preceding text.
/* The invalid input is ignored, to avoid complicating caller code.
@ -66,9 +77,9 @@
#define LEN(x) VSTRING_LEN(x)
#define END(x) vstring_end(x)
/* readlline - read one logical line */
/* readllines - read one logical line */
VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
{
int ch;
int next;
@ -86,13 +97,15 @@ VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
start = LEN(buf);
while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
VSTRING_ADDCH(buf, ch);
if (ch == '\n' && lineno != 0)
if (lineno != 0 && (ch == '\n' || LEN(buf) > start))
*lineno += 1;
/* Ignore comment line, all whitespace line, or empty line. */
for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++)
/* void */ ;
if (cp == END(buf) || *cp == '#')
vstring_truncate(buf, start);
else if (start == 0 && lineno != 0 && first_line != 0)
*first_line = *lineno;
/* Terminate at EOF or at the beginning of the next logical line. */
if (ch == VSTREAM_EOF)
break;
@ -115,7 +128,7 @@ VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"",
VSTREAM_PATH(fp), STR(buf),
LEN(buf) > 30 ? "..." : "");
return (readlline(buf, fp, lineno));
return (readllines(buf, fp, lineno, first_line));
}
/*

View File

@ -20,7 +20,9 @@
/*
* External interface.
*/
extern VSTRING *readlline(VSTRING *, VSTREAM *, int *);
extern VSTRING *readllines(VSTRING *, VSTREAM *, int *, int *);
#define readlline(bp, fp, lp) readllines((bp), (fp), (lp), (int *) 0)
/* LICENSE
/* .ad