2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 01:49:47 +00:00

postfix-2.11-20131217

This commit is contained in:
Wietse Venema 2013-12-17 00:00:00 -05:00 committed by Viktor Dukhovni
parent 33f88e4f81
commit 64700e1f71
98 changed files with 4884 additions and 1909 deletions

14
postfix/.indent.pro vendored
View File

@ -155,6 +155,7 @@
-TLMTP_STATE
-TLOCAL_EXP
-TLOCAL_STATE
-TLONG_NAME_MASK
-TMAC_EXP
-TMAC_HEAD
-TMAC_PARSE
@ -193,6 +194,7 @@
-TMKMAP_DB
-TMKMAP_DBM
-TMKMAP_OPEN_INFO
-TMKMAP_SDBM
-TMSG_STATS
-TMULTI_SERVER
-TMVECT
@ -206,10 +208,14 @@
-TOPTIONS
-TPC_DBMS_INFO
-TPC_EVAL_CTX
-TPC_MASTER_EDIT_REQ
-TPC_MASTER_ENT
-TPC_MASTER_FIELD_REQ
-TPC_PARAM_CTX
-TPC_PARAM_NODE
-TPC_PARAM_TABLE
-TPC_SERVICE_DEF
-TPC_SERVICE_PATTERN
-TPC_STRING_NV
-TPEER_NAME
-TPGSQL_NAME
@ -341,6 +347,7 @@
-TXSASL_CLIENT_CREATE_ARGS
-TXSASL_CLIENT_IMPL
-TXSASL_CLIENT_IMPL_INFO
-TXSASL_CYRUS_CB
-TXSASL_CYRUS_CLIENT
-TXSASL_CYRUS_ERROR_INFO
-TXSASL_CYRUS_SERVER
@ -352,18 +359,25 @@
-TXSASL_SERVER_CREATE_ARGS
-TXSASL_SERVER_IMPL
-TXSASL_SERVER_IMPL_INFO
-Tbind_props
-Tcipher_probe_t
-Tdane_digest
-Tfilter_ctx
-Tgeneral_name_stack_t
-Tiana_digest
-Toff_t
-Tregex_t
-Tregmatch_t
-Tsasl_conn_t
-Tsasl_secret_t
-Tsfsistat
-Tsigset_t
-Tsize_t
-Tsockaddr
-Tssize_t
-Tssl_cipher_stack_t
-Tssl_comp_stack_t
-Ttime_t
-Ttlsa_filter
-Tx509_extension_stack_t
-Tx509_stack_t

View File

@ -18218,6 +18218,13 @@ Apologies for any names omitted.
Factor out the master.cf line parser so that it can be
reused for "postconf -Me". File: postconf/postconf_master.c.
20130113
Feature: master.cf attribute namespace. "postconf -F" shows
individual master.cf fields as "service/type/attribute =
value", where attribute is "service", "type", "private",
"unprivileged", "wakeup", "process_limit", or "command".
20130121
Bugfix (introduced 20120307): the postconf -X option erased
@ -19232,9 +19239,161 @@ Apologies for any names omitted.
cleanup/cleanup_milter.c, cleanup/cleanup_state.c,
global/xtext.c, global/xtext.h, milter/test-milter.c.
20131122
Feature: "postcon -Fe service/type/attribute = value" edits
master.cf attribute values. The -e is optional. Example:
use "postconf -F "*/*/chroot = n" to turn off chroot on all
master.cf services. Files: postconf/postconf.h,
postconf/postconf.c, postconf/postcof_master.c,
postconf/postconf_edit.c.
20131124
Cleanup: remove extra blank line from ccformat output,
making it compatible with the script that Wietse actually
uses (this line was part of a test to detect file truncation,
but it is now obsolete). File: mantools/ccformat.
Feature: master.cf parameter namespace. "postconf -P" shows
master.cf parameter settings as "service/type/parameter =
value". This is applicable only to parameter settings in
master.cf. Files: postconf/postconf.h, postconf/postconf.c,
postconf/postcof_master.c, postconf/postconf_print.c.
Incompatibility: the master_service_disable syntax has
changed: use "service/type" instead of "service.type". The
new form is consistent with master.cf parameter namespaces.
The old form is still supported to avoid breaking existing
configurations. Files: global/master_service.c,
master/master_ent.c.
20131125
Feature: change, add or delete "-o parameter=value" setting
in master.cf. Examples: "postconf -P smtp/inet/parameter=value"
(add or modify "-o name=value" setting) and "postconf -P
smtp/inet/parameter" (delete "-o parameter=value" setting).
Files: util/argv.[hc], postconf/postconf.h,
postconf/postconf_edit.c, postconf_master.c.
20131126
Cleanup: Leave SSLv3 enabled with DANE. Viktor Dukhovni.
Files: proto/TLS_README.html proto/postconf.proto
tls/tls_client.c.
Cleanup: DANE support: Drop support for usage 0. It SHOULD
NOT be supported in DANE with SMTP, and we already don't
support digest TLSA RRs in this case, while full content
TLSA RRs are not recommended for DNS bloat reasons. Viktor
Dukhovni. Files: proto/postconf.proto src/global/mail_params.h
src/smtp/smtp.c src/tls/tls_dane.c src/tls/tls_misc.c.
Feature: TLS support: Support future digest algorithms
without re-compilation. Viktor Dukhovni. Files: .indent.pro
proto/postconf.proto src/tls/tls_dane.c.
Feature: DNS support: New configurable digest agility.
Viktor Dukhovni. Files: .indent.pro proto/TLS_README.html
proto/postconf.proto src/global/mail_params.h src/tls/tls_dane.c
src/tls/tls_misc.c.
20131127
Bugfix (introduced: 20090106): the postconf '-#' option
erased prior options. File: postconf/postconf.c.
20131129
Bugfix: Makefile example in MULTI_INSTANCE_README. Viktor
Dukhovni. File: proto/MULTI_INSTANCE_README.html.
20131130
Cleanup: simplify fingerprint security level implementation
in new DANE code. Viktor Dukhovni. Files: src/tls/tls.h
src/smtp/smtp_tls_policy.c src/tls/tls_dane.c
src/posttls-finger/posttls-finger.c.
20131209
Cleanup: safe_strtoul() did not report an error for empty
or all-space input (the code to report this was in the wrong
place). This was not a problem as long as safe_strtoul()
was used only for output from safe_ultostr(). Files:
global/safe_ultostr.c, global/safe_ultostr.in,
global/safe_ultostr.ref.
20131210
Documentation: updated description of SSL protocol controls.
In particular, enabled protocols are part of a contiguous
range. Viktor Dukhovni. Files: proto/TLS_README.html,
proto/postconf.proto.
Bugfix: DANE support: handle OpenSSL memory allocation
error. Viktor Dukhovni. File: tls/tls_dane.c.
Cleanup: LMDB_README was not installed. File: conf/postfix-files.
20131214
Portability: on some platforms posttls-finger now requires
explicitly linking libdl. File: posttls-finger/Makefile.in.
Cleanup: DANE support: extension gymnastics. Viktor Dukhovni.
File: tls/tls_dane.c.
Bugfix: DANE support: the wrap_cert() and wrap_key() calls
should never fail, but some callers ignored the return
value. The only failure is for lack of memory, so we use
msg_fatal() internally and change wrap_cert() and wrap_key()
to return void. Viktor Dukhovni. File: tls/tls_dane.c.
Bugfix: DANE support: avoid making DANE certificates with
replaced public-keys appear as if they were self-signed.
Viktor Dukhovni. File: tls/tls_dane.c.
Cleanup: DANE support: simplify grow_chain() to always apply
trust consistently. Viktor Dukhovni. File: tls/tls_dane.c.
Bugfix: DANE support: backport fixes from OpenSSL DANE
testing. Discard errors generated by raw TA key signature
checks. Record the tadepth as zero with self-signed depth
0 TAs. Robustness: Though it should never happen, don't
update the tadepth if already set. Viktor Dukhovni. Files:
tls/tls_dane.c, tls/tls_server.c.
20131215
Cleanup: OpenSSL "const" declarations have changed over
time. Viktor Dukhovni. Files: src/tls/tls.h, src/tls/tls_client.c,
src/tls/tls_dane.c, src/tls/tls_server.c.
20131216
Cleanup: TLS support. Eliminate calls of deprecated functions
before they are removed from OpenSSL. CRYPTO_thread_id is
deprecated and we don't need it. Replace the deprecated
ERR_remove_state() call with ERR_remove_thread_state(), and
use RSA_generate_key_ex(). Viktor Dukhovni. Files:
posttls-finger/posttls-finger.c, tls/tls_misc.c, tls/tls_rsa.c.
Cleanup: DANE support: Reduce #ifdef clutter to improve
redability and maintability. Viktor Dukhovni. File:
tls/tls_dane.c.
Future proofing: Tolerate disappearance of named bug-workaround
bits without invalidating user configurations. When support
for a bug workaround is removed from OpenSSL, the corresponding
bit is defined as zero (i.e. NOOP) intstead of causing
programs to break. Viktor Dukhovni. File: tls/tls_misc.c.
20131217
Portability: RSA_generate_key_ex() is not available on all
supported platforms, so this change is made conditional.
Enforce that this function will be used only for creating
a 512-bit ephemeral RSA key. Viktor Dukhovni. File:
tls/tls_rsa.c.

View File

@ -177,7 +177,7 @@ database when none exists.
generic: Makefile
@echo Creating $@
@rm -f $@.tmp
@printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp
@printf '%s\t%s+root=%s\n' root ${MTAADMIN} `uname -n` > $@.tmp
@mv $@.tmp generic
%.cdb: %

View File

@ -135,9 +135,10 @@ assume that the certificate for "server.example.com" was issued by
% ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm >> sseerrvveerr..ppeemm
* If you use RFC 6698 TLSA "2 0 1" or "2 1 1" records to specify root CA
* If you publish RFC 6698 TLSA "2 0 1" or "2 1 1" records to specify root CA
certificate digests, you must include the corresponding root CA
certificates in the "server.pem" certificate file.
certificates in the "server.pem" certificate file. See the documentation of
the tls_dane_trust_anchor_digest_enable main.cf parameter.
% ccaatt sseerrvveerr__cceerrtt..ppeemm iinntteerrmmeeddiiaattee__CCAA..ppeemm rroooott..ppeemm >> sseerrvveerr..ppeemm
@ -147,20 +148,13 @@ assume that the certificate for "server.example.com" was issued by
published TLSA records will typically cause the SMTP client to defer mail
delivery. The foregoing also applies to "2 0 2" and "2 1 2" TLSA records or
any other digest of a CA certificate, but it is expected that SHA256 will
be by far the most common digest for TLSA. You are strongly urged to
likewise include the root CA certificate in your server certificate file
even if you use "0 0 1" or "0 1 1" TLSA records. Some DANE implementations
in SMTP clients (Postfix among them) may treat RFC 6698 certificate usages
"0" and "2" interchangeably.
be by far the most common digest for TLSA.
By default, support for TLSA records that specify certificate usage "0" via
a digest is disabled in the Postfix SMTP client. As a best practice,
publish either "3 0 1" or "3 1 1" TLSA associations that specify the SHA256
digest of the server certificate public key with the alias-expanded
hostname of each STARTTLS capable SMTP server. These continue to work when
a certificate is renewed with the same public/private key pair. See the
documentation of the tls_dane_trust_anchor_digest_enable main.cf parameter
for details.
As a best practice, publish either "3 0 1" or "3 1 1" TLSA associations
that specify the SHA256 digest of the server certificate public key with
the alias-expanded hostname of each STARTTLS capable SMTP server. These
continue to work when a certificate is renewed with the same public/private
key pair.
For instructions on how to compute the digest of a certificate or its public
key for use in TLSA records, see the documentation of the
@ -418,7 +412,7 @@ from scratch.
Since Postfix uses multiple smtpd(8) service processes, an in-memory cache is
not sufficient for session re-use. Clients store at most one cached session per
server and are very unlikey to repeatedly connect to the same server process.
server and are very unlikely to repeatedly connect to the same server process.
Thus session caching in the Postfix SMTP server generally requires a shared
cache (an alternative available with Postfix >= 2.11 is described below).
@ -614,7 +608,8 @@ configurations with no server certificates that use oonnllyy the anonymous c
This is enabled by explicitly setting "smtpd_tls_cert_file = none" and not
specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file.
Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade ciphers:
Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3, with high grade
ciphers:
/etc/postfix/main.cf:
smtpd_tls_cert_file = /etc/postfix/cert.pem
@ -622,9 +617,9 @@ Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade ciphers:
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5
smtpd_tls_security_level = encrypt
# Preferred form with Postfix >= 2.5:
# Preferred syntax with Postfix >= 2.5:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
If you want to take advantage of ciphers with ephemeral Diffie-Hellman (EDH)
@ -656,21 +651,25 @@ Examples:
smtpd_tls_eecdh_grade = strong
Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS
servers to preempt the TLS client's cipher preference list. This is possible
only with SSLv3 and later, as in SSLv2 the client chooses the cipher from a
list supplied by the server.
servers to preempt the TLS client's cipher-suite preference list. This is
possible only with SSLv3 and later, as in SSLv2 the client chooses the cipher-
suite from a list supplied by the server.
By default, the OpenSSL server selects the client's most preferred cipher that
the server supports. With SSLv3 and later, the server may choose its own most
preferred cipher that is supported (offered) by the client. Setting
"tls_preempt_cipherlist = yes" enables server cipher preferences. The default
OpenSSL behavior applies with "tls_preempt_cipherlist = no".
By default, the OpenSSL server selects the client's most preferred cipher-suite
that the server supports. With SSLv3 and later, the server may choose its own
most preferred cipher-suite that is supported (offered) by the client. Setting
"tls_preempt_cipherlist = yes" enables server cipher-suite preferences. The
default OpenSSL behavior applies with "tls_preempt_cipherlist = no".
While server cipher selection may in some cases lead to a more secure or
performant cipher choice, there is some risk of interoperability issues. In the
past, some SSL clients have listed lower priority ciphers that they did not
implement correctly. If the server chooses a cipher that the client prefers
less, it may select a cipher whose client implementation is flawed.
While server cipher-suite selection may in some cases lead to a more secure or
performant cipher-suite choice, there is some risk of interoperability issues.
In the past, some SSL clients have listed lower priority ciphers that they did
not implement correctly. If the server chooses a cipher that the client prefers
less, it may select a cipher whose client implementation is flawed. Most
notably Windows 2003 Microsoft Exchange servers have flawed implementations of
DES-CBC3-SHA, which OpenSSL considers stronger than RC4-SHA. Enabling server
cipher-suite selection may create interoperability issues with Windows 2003
Microsoft Exchange clients.
MMiisscceellllaanneeoouuss sseerrvveerr ccoonnttrroollss
@ -916,78 +915,74 @@ level.
The "dane" level is a stronger form of opportunistic TLS that is resistant to
man in the middle and downgrade attacks when the destination domain uses DNSSEC
to publish DANE TLSA records for its MX hosts. If a remote SMTP server has
usable DANE TLSA records, these will be used to authenticate the server. If
TLSA records are published for a given remote SMTP server (implying TLS
support), but are not usable due to unsupported parameters, the Postfix SMTP
client will use mandatory unauthenticated TLS. Otherwise, the Postfix SMTP
client behavior is the same as with may.
"usable" (see RFC 6698) DANE TLSA records, the server connection will be
authenticated. When DANE authentication fails, there is no fallback to
unauthenticated or plaintext delivery.
If TLSA records are published for a given remote SMTP server (implying TLS
support), but are all "unusable" due to unsupported parameters or malformed
data, the Postfix SMTP client will use mandatory unauthenticated TLS.
Otherwise, when no TLSA records are published, the Postfix SMTP client behavior
is the same as with may.
TLSA records must be published in DNSSEC validated DNS zones. Any TLSA records
in DNS zones not protected via DNSSEC are ignored. The Postfix SMTP client will
not look for TLSA records associated with MX hosts whose "A" or "AAAA" records
lie in an "insecure" DNS zone. Such lookups have been observed to cause
interoperability issues with poorly implemented DNS servers, and are in any
case not expected to ever yield "secure" results, since that would require a
very unlikely DLV DNS trust anchor configured between the host record and the
associated "_25._tcp" child TLSA record.
The "dane-only" level is a form of secure-channel TLS based on the DANE PKI. If
usable TLSA records are present these are used to authenticate the remote SMTP
server. Otherwise, or when server certificate verification fails, delivery via
the server in question tempfails.
"usable" TLSA records are present these are used to authenticate the remote
SMTP server. Otherwise, or when server certificate verification fails, delivery
via the server in question tempfails.
At both security levels, the TLS policy for the destination is obtained via
TLSA records validated with DNSSEC. For TLSA policy to be in effect, the
destination domain's containing DNS zone must be signed and the Postfix SMTP
client's operating system must be configured to send its DNS queries to a
recursive DNS nameserver that is able to validate the signed records. Each MX
host's DNS zone should also be signed, and should publish DANE TLSA (RFC 6698)
records that specify how that MX host's TLS certificate is to be verified. TLSA
records do not preempt the normal SMTP MX host selection algorithm, if some MX
hosts support TLSA and others do not, TLS security will vary from delivery to
delivery. It is up to the domain owner to configure their MX hosts and their
DNS sensibly. To configure the Postfix SMTP client for DNSSEC lookups see the
documentation for the smtp_dns_support_level main.cf parameter. The
tls_dane_trust_anchor_digest_enable main.cf parameter controls optional support
for trust-anchor digest TLSA records.
host's DNS zone needs to also be signed, and needs to publish DANE TLSA (RFC
6698) records that specify how that MX host's TLS certificate is to be
verified.
The Postfix SMTP client deviates from RFC 6698 in cases where strict adherence
is likely to create opportunities for delayed (or eventually bounced) email
with no substantive security gain. Most notably, it is not expected that
smtp_tls_CAfile and smtp_tls_CApath can reasonably include every public CA that
a remote SMTP server's administrator may believe to be well-known. Therefore,
certificate usages "0" and "2" from RFC 6698 which are intended to "constrain"
existing PKI trust, are instead treated as "trust assertions" and mapped to "1"
and "3" respectively. That is, with certificate usage "0" and "2", Postfix will
not require the remote SMTP server's certificate to be trusted with respect to
any locally defined public CAs, it is the domain owner's responsibility to
ensure that the certificate associations in their TLSA records are appropriate
to authenticate their SMTP servers.
TLSA records do not preempt the normal SMTP MX host selection algorithm, if
some MX hosts support TLSA and others do not, TLS security will vary from
delivery to delivery. It is up to the domain owner to configure their MX hosts
and their DNS sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the smtp_dns_support_level main.cf parameter. The
tls_dane_trust_anchor_digest_enable main.cf parameter controls support for
trust-anchor digest TLSA records. The tls_dane_digests and
tls_dane_digest_agility parameters control the list of supported digests and
digest downgrade attack resistance.
In addition, the Postfix SMTP client does not assume that the remote SMTP
server will necessarily be configured to present the certificate of any usage
"0" root CA in its TLS protocol certificate_list. Therefore, support for usage
"0" certificate and public-key digests is disabled by default, see
tls_dane_trust_anchor_digest_enable for details. While undigested trust-anchor
certificates in TLSA records are supported, publishing complete certificates in
DNS is unwise given the resulting excessively large DNS record sizes.
Therefore, in its default configuration the Postfix SMTP client essentially
supports only certificate usages "1", "2" and "3" (with "1" treated as though
it were "3").
DANE for SMTP MTAs deviates in some details from the baseline DANE protocol in
RFC 6698. Most notably, it is not expected that SMTP MTAs can reasonably
include every public CA that a remote SMTP server's administrator may believe
to be well-known. Nor is there an interactive user to "click OK" when
authentication fails.
Finally, the interaction of DANE with MX hostnames that are CNAMEs differs from
the draft specification in the names used to construct the associated TLSA
queries. When the MX hostname is a CNAME, the draft proposal to use the
unexpanded MX hostname in TLSA lookups is fragile and unintuitive. For this to
work, the domain owner has to either duplicate the TLSA records of the target
(host, service) pair in his own DNS or furnish the target host with an
additional certificate and private key that would be negotiated via SNI.
Neither of these are robust or easy to manage. It is far better to expand the
CNAME recursively to the underlying target hostname (keeping track of DNSSEC
validation along the way) and to use the expanded name to construct the TLSA
query and, if appropriate, in server certificate name checks. This is the
approach taken by the Postfix SMTP client, and if sanity prevails will also be
the approach taken in the final standard.
Therefore, certificate usages "0" and "1" from RFC 6698 which are intended to
"constrain" existing PKI trust, are not supported. TLSA records with usage "0"
are treated as "unusable". TLSA records with usage "1" are instead treated as
"trust assertions" and mapped to usage "3". Specifically, with certificate
usage "1", Postfix will not require the remote SMTP server's certificate to be
trusted with respect to any locally defined public CAs, it is the domain
owner's responsibility to ensure that the certificate associations in their
TLSA records are appropriate to authenticate their SMTP servers.
The Postfix SMTP client supports only certificate usages "2" and "3" (with "1"
treated as though it were "3"). See tls_dane_trust_anchor_digest_enable for
usage "2" usability considerations. Support for certificate usage "1" is an
experiment, it may be withdrawn in the future. Server operators SHOULD NOT
publish TLSA records with usage "1".
When usable TLSA records are obtained for the remote SMTP server the Postfix
SMTP client is obligated to include the SNI TLS extension in its SSL client
hello message. This may help the remote SMTP server live up to its promise to
provide a certificate that matches its TLSA records. Since TLS extensions
require TLS 1.0 or later, the Postfix SMTP client must disable SSLv2 and SSLv3
when SNI is required. If you use "dane" or "dane-only", do not disable TLSv1,
except perhaps via the policy table for destinations which you are sure will
support TLSv1.1 or TLSv1.2.
SMTP client sends the SNI TLS extension in its SSL client hello message. This
may help the remote SMTP server live up to its promise to provide a certificate
that matches its TLSA records.
For purposes of protocol and cipher selection, the "dane" security level is
treated like a "mandatory" TLS security level, and weak ciphers and protocols
@ -1010,8 +1005,8 @@ administrators should publish such EE records in preference to all other types.
The pre-requisites for DANE support in the Postfix SMTP client are:
* A compile-time OpenSSL library that supports the TLS SNI extension and the
"sha256" and "sha512" message digests.
* A compile-time OpenSSL library that supports the TLS SNI extension and
"SHA-2" message digests.
* A compile-time DNS resolver library that supports DNSSEC. Postfix binaries
built on an older system will not support DNSSEC even if deployed on a
system with an updated resolver library.
@ -1566,9 +1561,9 @@ security policy.
On the SMTP client, there are further complications. When delivering mail to a
given domain, in contrast to HTTPS, one rarely uses the domain name directly as
the target host of the SMTP session. More typically, one uses MX lookups -
these are usually unauthenticated - to obtain the domain's SMTP server hostname
(s). When, as is current practice, the client verifies the insecurely obtained
MX hostname, it is subject to a DNS man-in-the-middle attack.
- these are usually unauthenticated -- to obtain the domain's SMTP server
hostname(s). When, as is current practice, the client verifies the insecurely
obtained MX hostname, it is subject to a DNS man-in-the-middle attack.
Adoption of DNSSEC and RFC6698 (DANE) may gradually (as domains implement
DNSSEC and publish TLSA records for their MX hosts) address the DNS man-in-the-
@ -1660,21 +1655,18 @@ ddaannee
TLSA records in DNSSEC. If no TLSA records are found, the effective
security level used is may. If TLSA records are found, but none are usable,
the effective security level is encrypt. When usable TLSA records are
obtained for the remote SMTP server, SSLv2 and SSLv3 are automatically
disabled (see smtp_tls_mandatory_protocols), and the server certificate
must match the TLSA records. The tls_dane_trust_anchor_digest_enable
parameter controls optional support for trust-anchor digest TLSA records.
RFC 6698 (DANE) TLS authentication and DNSSEC support is available with
Postfix 2.11 and later.
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.
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
connection is made to the server. When usable TLSA records are obtained for
the remote SMTP server, SSLv2 and SSLv3 are automatically disabled (see
the remote SMTP server, SSLv2 is automatically disabled (see
smtp_tls_mandatory_protocols), and the server certificate must match the
TLSA records. The tls_dane_trust_anchor_digest_enable parameter controls
optional support for trust-anchor digest TLSA records. RFC 6698 (DANE) TLS
authentication and DNSSEC support is available with Postfix 2.11 and later.
TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
available with Postfix 2.11 and later.
ffiinnggeerrpprriinntt
Certificate fingerprint verification. Available with Postfix 2.5 and later.
At this security level, there are no trusted certificate authorities. The
@ -1745,9 +1737,8 @@ Example:
/etc/postfix/tls_policy:
example.edu none
example.mil may
example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high
example.com verify
match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high
example.gov encrypt ciphers=high
example.com verify match=hostname:dot-nexthop ciphers=high
example.net secure
.example.net secure match=.example.net:example.net
[mail.example.org]:587 secure match=nexthop
@ -1838,7 +1829,7 @@ Example:
smtp_tls_exclude_ciphers = aNULL
# Preferred form with Postfix >= 2.5:
smtp_tls_mandatory_protocols = !SSLv2
# Alternative form.
# Legacy form for Postifx < 2.5:
smtp_tls_mandatory_protocols = SSLv3, TLSv1
# Also available with Postfix >= 2.6:
smtp_tls_ciphers = export

View File

@ -1,3 +1,5 @@
This is the Postfix 2.11 (experimental) branch.
The stable Postfix release is called postfix-2.10.x where 2=major
release number, 10=minor release number, x=patchlevel. The stable
release never changes except for patches that address bugs or
@ -14,6 +16,156 @@ specifies the release date of a stable release or snapshot release.
If you upgrade from Postfix 2.9 or earlier, read RELEASE_NOTES-2.10
before proceeding.
Incompatible changes with snapshot 20131217
===========================================
The master_service_disable syntax has changed: use "service/type"
instead of "service.type". The new form is consistent with master.cf
parameter namespaces. The old form is still supported to avoid
breaking existing configurations.
Major changes with with snapshot 20131217
=========================================
Support for advanced master.cf query and update operations. This
was implemented primarily to support automated system management
tools.
The goal is to make all Postfix master.cf details accessible as
lists of "name=value" pairs, where the names are organized into
structured name spaces. This allows other programs to query
information or request updates, without having to worry about the
exact layout of master.cf files.
Managing master.cf service attributes
-------------------------------------
First, an example that shows the smtp/inet service in the traditional
form:
$ postconf -M smtp/inet
smtp inet n - n - - smtpd
Different variants of this command show different amounts of output.
For example, "postconf -M smtp" enumerates all services that have
a name "smtp" and any service type ("inet", "unix", etc.), and
"postconf -M" enumerates all master.cf services.
General rule: each name component that is not present becomes a "*"
wildcard.
Coming back to the above example, the postconf -F option can now
enumerate the smtp/inet service fields as follows:
$ postconf -F smtp/inet
smtp/inet/service = smtp
smtp/inet/type = inet
smtp/inet/private = n
smtp/inet/unprivileged = -
smtp/inet/chroot = n
smtp/inet/wakeup = -
smtp/inet/process_limit = -
smtp/inet/command = smtpd
This form makes it very easy to change one field in master.cf.
For example to turn on chroot on the smtp/inet service you use:
$ postconf -F smtp/inet/chroot=y
$ postfix reload
Moreover, with "-F" you can specify "*" for service name or service
type to get a wild-card match. For example, to turn off chroot on
all Postfix daemons, use this:
$ postconf -F '*/*/chroot=n'
$ postfix reload
Managing master.cf service "-o parameter=value" settings
--------------------------------------------------------
For a second example, let's look at the submission service. This
service typically has multiple "-o parameter=value" overrides. First
the traditional view:
$ postconf -Mf submission
submission inet n - n - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
...
The postconf -P option can now enumerate these parameters as follows:
$ postconf -P submission
submission/inet/smtpd_sasl_auth_enable = yes
submission/inet/smtpd_tls_security_level = encrypt
...
Again, this form makes it very easy to modify one parameter
setting. For example, to change the smtpd_tls_security_level setting
for the submission/inet service:
$ postconf -P 'submission/inet/smtpd_tls_security_level=may'
You can create or remove a parametername=parametervalue setting:
Create:
$ postconf -P 'submission/inet/parametername=parametervalue'
Remove:
$ postconf -PX submission/inet/parametername
Finally, always execute "postfix reload" after updating master.cf.
Managing master.cf service entries
----------------------------------
Finally, adding master.cf entries is possible, but currently this
does not yet have "advanced" support. It can only be done at the
level of the traditional master.cf file format.
Suppose that you need to configure a Postfix SMTP client that will
handle slow email deliveries. To implement this you need to clone
the smtp/unix service settings and create a new delay/unix service.
First, you would enumerate the smtp/unix service like this:
$ postconf -M smtp/unix
smtp unix - - n - - smtp
Then you would copy those fields (except the first field) by hand
to create the delay/unix service:
$ postconf -M delay/unix="delay unix - - n - - smtp"
To combine the above steps in one command:
$ postconf -M delay/unix="`postconf -M smtp/unix|awk '{$1 = "delay"}'`"
This is perhaps not super-convenient for manual cloning, but it
should be sufficient for programmatic configuration management.
Again, always execute "postfix reload" after updating master.cf.
Deleting or commenting out master.cf entries
--------------------------------------------
The -X (delete entry) and -# (comment out entry) options already
exist for main.cf, and they now also work work for entire master.cf
entries:
Remove main.cf or master.cf entry:
$ postconf -X parametername
$ postconf -MX delay/unix
Comment out main.cf or master.cf entry:
$ postconf -# parametername
$ postconf -M# delay/unix
As with main.cf, there is no support to "undo" master.cf changes
that are made with -X or -#.
Again, always execute "postfix reload" after updating master.cf.
Major changes with snapshot 20131031
====================================

View File

@ -264,6 +264,7 @@ $readme_directory/INSTALL:f:root:-:644
$readme_directory/IPV6_README:f:root:-:644
$readme_directory/LDAP_README:f:root:-:644
$readme_directory/LINUX_README:f:root:-:644
$readme_directory/LMDB_README:f:root:-:644
$readme_directory/LOCAL_RECIPIENT_README:f:root:-:644
$readme_directory/MACOSX_README:f:root:-:644:o
$readme_directory/MAILDROP_README:f:root:-:644
@ -319,6 +320,7 @@ $html_directory/INSTALL.html:f:root:-:644
$html_directory/IPV6_README.html:f:root:-:644
$html_directory/LDAP_README.html:f:root:-:644
$html_directory/LINUX_README.html:f:root:-:644
$html_directory/LMDB_README.html:f:root:-:644
$html_directory/LOCAL_RECIPIENT_README.html:f:root:-:644
$html_directory/MAILDROP_README.html:f:root:-:644
$html_directory/MILTER_README.html:f:root:-:644

View File

@ -428,13 +428,13 @@ tables are implemented:
<dl>
<dt> <b><a href="DATABASE_README.html#types">unix</a>:passwd.byname</b> </dt>
<dt> <b>unix:passwd.byname</b> </dt>
<dd>The table is the UNIX password database. The key is a login
name. The result is a password file entry in passwd(5) format.
</dd>
<dt> <b><a href="DATABASE_README.html#types">unix</a>:group.byname</b> </dt>
<dt> <b>unix:group.byname</b> </dt>
<dd> The table is the UNIX group database. The key is a group name.
The result is a group file entry in group(5) format. </dd>

View File

@ -233,7 +233,7 @@ creates a "generic" database when none exists. </p>
generic: Makefile
@echo Creating $@
@rm -f $@.tmp
@printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` &gt; $@.tmp
@printf '%s\t%s+root=%s\n' root ${MTAADMIN} `uname -n` &gt; $@.tmp
@mv $@.tmp generic
%.<a href="CDB_README.html">cdb</a>: %

View File

@ -209,7 +209,7 @@ described in the <a href="postconf.5.html">postconf(5)</a> manual page. </p>
<a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> = <a href="postconf.5.html#reject_unauth_pipelining">reject_unauth_pipelining</a>
# Enforce mail volume quota via policy service callouts.
<a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> = <a href="postconf.5.html#check_policy_service">check_policy_service</a> <a href="DATABASE_README.html#types">unix</a>:private/policy
<a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> = <a href="postconf.5.html#check_policy_service">check_policy_service</a> unix:private/policy
</pre>
<p> Each restriction list is evaluated from left to right until

View File

@ -235,8 +235,8 @@ or to a UNIX-domain socket. Examples: </p>
<blockquote>
<pre>
inet:127.0.0.1:9998
<a href="DATABASE_README.html#types">unix</a>:/some/where/policy
<a href="DATABASE_README.html#types">unix</a>:private/policy
unix:/some/where/policy
unix:private/policy
</pre>
</blockquote>
@ -261,7 +261,7 @@ daemon, you would use something like this: </p>
6 <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
7 ...
8 <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
9 <a href="postconf.5.html#check_policy_service">check_policy_service</a> <a href="DATABASE_README.html#types">unix</a>:private/policy
9 <a href="postconf.5.html#check_policy_service">check_policy_service</a> unix:private/policy
10 ...
11 <a href="postconf.5.html#transport_time_limit">policy_time_limit</a> = 3600
</pre>
@ -411,7 +411,7 @@ processes only: </p>
7 <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
8 ...
9 <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
10 <a href="postconf.5.html#check_policy_service">check_policy_service</a> <a href="DATABASE_README.html#types">unix</a>:private/greylist
10 <a href="postconf.5.html#check_policy_service">check_policy_service</a> unix:private/greylist
11 ...
</pre>
</blockquote>
@ -454,7 +454,7 @@ a built-in suffix (in the above example: "_time_limit"). </p>
</ul>
<p> With Solaris &lt; 9, or Postfix &lt; 2.10 on any Solaris
version, use inet: style sockets instead of <a href="DATABASE_README.html#types">unix</a>:
version, use inet: style sockets instead of unix:
style, as detailed in the "<a href="#client_config">Policy
client/server configuration</a>" section above. </p>
@ -492,7 +492,7 @@ forged MAIL FROM domains could be found at
6 <a href="postconf.5.html#check_sender_access">check_sender_access</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_access
7 ...
8 <a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> = greylist
9 greylist = <a href="postconf.5.html#check_policy_service">check_policy_service</a> <a href="DATABASE_README.html#types">unix</a>:private/greylist
9 greylist = <a href="postconf.5.html#check_policy_service">check_policy_service</a> unix:private/greylist
10
11 /etc/postfix/sender_access:
12 aol.com greylist
@ -548,7 +548,7 @@ most of the delays and most of the database pollution problem. </p>
4 ...
5 <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
6 <a href="postconf.5.html#check_sender_access">check_sender_access</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_access
7 <a href="postconf.5.html#check_policy_service">check_policy_service</a> <a href="DATABASE_README.html#types">unix</a>:private/policy
7 <a href="postconf.5.html#check_policy_service">check_policy_service</a> unix:private/policy
8 ...
9
10 /etc/postfix/sender_access:

View File

@ -226,9 +226,11 @@ size of the server TLS handshake. </p>
</pre>
</blockquote>
<li> <p> If you use <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> TLSA "2 0 1" or "2 1 1" records to
<li> <p> If you publish <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> TLSA "2 0 1" or "2 1 1" records to
specify root CA certificate digests, you must include the corresponding
root CA certificates in the "server.pem" certificate file. </p>
root CA certificates in the "server.pem" certificate file. See the
documentation of the <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> <a href="postconf.5.html">main.cf</a>
parameter. </p>
<blockquote>
<pre>
@ -236,29 +238,20 @@ root CA certificates in the "server.pem" certificate file. </p>
</pre>
</blockquote>
<p> Remote SMTP clients will
be able to use the TLSA record you publish (which only contains the
certificate digest) only if they have access to the corresponding
certificate. Failure to verify certificates per the server's
published TLSA records will typically cause the SMTP client to defer
mail delivery. The foregoing also applies to "2 0 2" and "2 1 2"
TLSA records or any other digest of a CA certificate, but it is
expected that SHA256 will be by far the most common digest for TLSA.
You are <i>strongly</i> urged to likewise include the root CA
certificate in your server certificate file even if you use "0 0
1" or "0 1 1" TLSA records. Some DANE implementations in SMTP
clients (Postfix among them) may treat <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> certificate usages
"0" and "2" interchangeably. </p>
<p> Remote SMTP clients will be able to use the TLSA record you
publish (which only contains the certificate digest) only if they
have access to the corresponding certificate. Failure to verify
certificates per the server's published TLSA records will typically
cause the SMTP client to defer mail delivery. The foregoing also
applies to "2 0 2" and "2 1 2" TLSA records or any other digest of
a CA certificate, but it is expected that SHA256 will be by far the
most common digest for TLSA. </p>
<p>By default, support for TLSA records that specify certificate
usage "0" via a digest is disabled in the Postfix SMTP client. As
a best practice, publish either "3 0 1" or "3 1 1" TLSA associations
that specify the SHA256 digest of the server certificate public key
with the alias-expanded hostname of each STARTTLS capable SMTP
server. These continue to work when a certificate is renewed with
the same public/private key pair. See the documentation of the
<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> <a href="postconf.5.html">main.cf</a> parameter for details.
</p>
<p> As a best practice, publish either "3 0 1" or "3 1 1" TLSA
associations that specify the SHA256 digest of the server certificate
public key with the alias-expanded hostname of each STARTTLS capable
SMTP server. These continue to work when a certificate is renewed
with the same public/private key pair. </p>
</ul>
@ -614,7 +607,7 @@ from scratch. </p>
<p> Since Postfix uses multiple <a href="smtpd.8.html">smtpd(8)</a> service processes, an
in-memory cache is not sufficient for session re-use. Clients store
at most one cached session per server and are very unlikey to
at most one cached session per server and are very unlikely to
repeatedly connect to the same server process. Thus session caching
in the Postfix SMTP server generally requires a shared cache (an
alternative available with Postfix &ge; 2.11 is described below).
@ -861,8 +854,8 @@ certificates</a> that use <b>only</b> the anonymous ciphers. This is
enabled by explicitly setting "<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = none"
and not specifying an <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> or <a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>. </p>
<p> Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade
ciphers: </p>
<p> Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3,
with high grade ciphers: </p>
<blockquote>
<pre>
@ -872,9 +865,9 @@ ciphers: </p>
<a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_mandatory_ciphers</a> = high
<a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_mandatory_exclude_ciphers</a> = aNULL, MD5
<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> = encrypt
# Preferred form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = TLSv1
</pre>
</blockquote>
@ -918,23 +911,27 @@ secure for most situations. </p>
</blockquote>
<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
allows TLS servers to preempt the TLS client's cipher preference list.
allows TLS servers to preempt the TLS client's cipher-suite preference list.
This is possible only with SSLv3 and later, as in SSLv2 the client
chooses the cipher from a list supplied by the server. </p>
chooses the cipher-suite from a list supplied by the server. </p>
<p> By default, the OpenSSL server selects the client's most preferred
cipher that the server supports. With SSLv3 and later, the server
may choose its own most preferred cipher that is supported (offered)
cipher-suite that the server supports. With SSLv3 and later, the server
may choose its own most preferred cipher-suite that is supported (offered)
by the client. Setting "<a href="postconf.5.html#tls_preempt_cipherlist">tls_preempt_cipherlist</a> = yes" enables server
cipher preferences. The default OpenSSL behavior applies with
cipher-suite preferences. The default OpenSSL behavior applies with
"<a href="postconf.5.html#tls_preempt_cipherlist">tls_preempt_cipherlist</a> = no". </p>
<p> While server cipher selection may in some cases lead to a more secure
or performant cipher choice, there is some risk of interoperability
issues. In the past, some SSL clients have listed lower priority ciphers
that they did not implement correctly. If the server chooses a cipher
that the client prefers less, it may select a cipher whose client
implementation is flawed. </p>
<p> While server cipher-suite selection may in some cases lead to
a more secure or performant cipher-suite choice, there is some risk
of interoperability issues. In the past, some SSL clients have
listed lower priority ciphers that they did not implement correctly.
If the server chooses a cipher that the client prefers less, it may
select a cipher whose client implementation is flawed. Most notably
Windows 2003 Microsoft Exchange servers have flawed implementations
of DES-CBC3-SHA, which OpenSSL considers stronger than RC4-SHA.
Enabling server cipher-suite selection may create interoperability
issues with Windows 2003 Microsoft Exchange clients. </p>
<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
@ -1251,17 +1248,30 @@ the mandatory "dane-only" level. </p>
href="#client_tls_may">opportunistic</a> TLS that is resistant to
man in the middle and downgrade attacks when the destination domain
uses DNSSEC to publish DANE TLSA records for its MX hosts. If a
remote SMTP server has usable DANE TLSA records, these will be used
to authenticate the server. If TLSA records are published for a
given remote SMTP server (implying TLS support), but are not usable
due to unsupported parameters, the Postfix SMTP client will use <a
remote SMTP server has "usable" (see <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>) DANE TLSA records,
the server connection will be authenticated. When DANE authentication
fails, there is no fallback to unauthenticated or plaintext delivery. </p>
<p> If TLSA records are published for a given remote SMTP server
(implying TLS support), but are all "unusable" due to unsupported
parameters or malformed data, the Postfix SMTP client will use <a
href="#client_tls_encrypt">mandatory</a> unauthenticated TLS.
Otherwise, the Postfix SMTP client behavior is the same as with <a
href="#client_tls_may">may</a>. </p>
Otherwise, when no TLSA records are published, the Postfix SMTP
client behavior is the same as with <a href="#client_tls_may">may</a>. </p>
<p> TLSA records must be published in DNSSEC validated DNS zones.
Any TLSA records in DNS zones not protected via DNSSEC are ignored.
The Postfix SMTP client will not look for TLSA records associated
with MX hosts whose "A" or "AAAA" records lie in an "insecure" DNS
zone. Such lookups have been observed to cause interoperability
issues with poorly implemented DNS servers, and are in any case not
expected to ever yield "secure" results, since that would require
a very unlikely DLV DNS trust anchor configured between the host
record and the associated "_25._tcp" child TLSA record. </p>
<p> The "dane-only" level is a form of <a
href="#client_tls_secure">secure-channel</a> TLS based on the DANE PKI.
If usable TLSA records are present these are used to authenticate the
If "usable" TLSA records are present these are used to authenticate the
remote SMTP server. Otherwise, or when server certificate verification
fails, delivery via the server in question tempfails. </p>
@ -1271,73 +1281,51 @@ to be in effect, the destination domain's containing DNS zone must
be signed and the Postfix SMTP client's operating system must be
configured to send its DNS queries to a recursive DNS nameserver
that is able to validate the signed records. Each MX host's DNS
zone should also be signed, and should publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>)
zone needs to also be signed, and needs to publish DANE TLSA (<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>)
records that specify how that MX host's TLS certificate is to be
verified. TLSA records do not preempt the normal SMTP MX host
verified. </p>
<p> TLSA records do not preempt the normal SMTP MX host
selection algorithm, if some MX hosts support TLSA and others do
not, TLS security will vary from delivery to delivery. It is up
to the domain owner to configure their MX hosts and their DNS
sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a> <a href="postconf.5.html">main.cf</a>
parameter. The <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> <a href="postconf.5.html">main.cf</a> parameter
controls optional support for trust-anchor digest TLSA records.
controls support for trust-anchor digest TLSA records. The
<a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a> and tls_dane_digest_agility parameters control
the list of supported digests and digest downgrade attack resistance.
</p>
<p> The Postfix SMTP client deviates from <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> in cases where
strict adherence is likely to create opportunities for delayed (or
eventually bounced) email with no substantive security gain. Most
notably, it is not expected that <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> and <a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a>
can reasonably include every public CA that a remote SMTP server's
administrator may believe to be well-known. Therefore, certificate
usages "0" and "2" from <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> which are intended to "constrain"
existing PKI trust, are instead treated as "trust assertions" and
mapped to "1" and "3" respectively. That is, with certificate usage
"0" and "2", Postfix will not require the remote SMTP server's
certificate to be trusted with respect to any locally defined public
CAs, it is the domain owner's responsibility to ensure that the
certificate associations in their TLSA records are appropriate
to authenticate their SMTP servers. </p>
<p> DANE for SMTP MTAs deviates in some details from the baseline
DANE protocol in <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>. Most notably, it is not expected that
SMTP MTAs can reasonably include every public CA that a remote SMTP
server's administrator may believe to be well-known. Nor is there
an interactive user to "click OK" when authentication fails. </p>
<p> In addition, the Postfix SMTP client does not assume that the
remote SMTP server will necessarily be configured to present the
certificate of any usage "0" root CA in its TLS protocol <a
href="https://tools.ietf.org/html/rfc2246#section-7.4.2">certificate_list</a>.
Therefore, support for usage "0" certificate and public-key digests
is disabled by default, see <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> for
details. While undigested trust-anchor certificates in TLSA records
are supported, publishing complete certificates in DNS is unwise
given the resulting excessively large DNS record sizes. Therefore,
in its default configuration the Postfix SMTP client essentially
supports only certificate usages "1", "2" and "3" (with "1" treated as
though it were "3"). </p>
<p> Therefore, certificate usages "0" and "1" from <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> which
are intended to "constrain" existing PKI trust, are not supported.
TLSA records with usage "0" are treated as "unusable". TLSA records
with usage "1" are instead treated as "trust assertions" and mapped
to usage "3". Specifically, with certificate usage "1", Postfix
will not require the remote SMTP server's certificate to be trusted
with respect to any locally defined public CAs, it is the domain
owner's responsibility to ensure that the certificate associations
in their TLSA records are appropriate to authenticate their SMTP
servers. </p>
<p> Finally, the interaction of DANE with MX hostnames that are
CNAMEs differs from the draft specification in the names used to
construct the associated <a
href="https://tools.ietf.org/html/draft-ietf-dane-srv-02#section-3.2">TLSA
queries</a>. When the MX hostname is a CNAME, the draft proposal
to use the unexpanded MX hostname in TLSA lookups is fragile and
unintuitive. For this to work, the domain owner has to either
duplicate the TLSA records of the target (host, service) pair in
his own DNS or furnish the target host with an additional
certificate and private key that would be negotiated via SNI.
Neither of these are robust or easy to manage. It is far better
to expand the CNAME recursively to the underlying target hostname
(keeping track of DNSSEC validation along the way) and to use the
expanded name to construct the TLSA query and, if appropriate, in
server certificate name checks. This is the approach taken by the
Postfix SMTP client, and if sanity prevails will also be the approach
taken in the final standard. </p>
<p> The Postfix SMTP client supports only certificate usages "2"
and "3" (with "1" treated as though it were "3"). See
<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> for usage "2" usability
considerations. Support for certificate usage "1" is an experiment,
it may be withdrawn in the future. Server operators SHOULD NOT
publish TLSA records with usage "1". </p>
<p> When usable TLSA records are obtained for the remote SMTP server
the Postfix SMTP client is obligated to include the SNI TLS extension
in its SSL client hello message. This may help the remote SMTP
server live up to its promise to provide a certificate that matches
its TLSA records. Since TLS extensions require TLS 1.0 or later,
the Postfix SMTP client must disable SSLv2 and SSLv3 when SNI is
required. If you use "dane" or "dane-only", do not disable TLSv1,
except perhaps via the policy table for destinations which you are
sure will support TLSv1.1 or TLSv1.2. </p>
the Postfix SMTP client sends the SNI TLS extension in its SSL
client hello message. This may help the remote SMTP server live
up to its promise to provide a certificate that matches its TLSA
records. </p>
<p> For purposes of protocol and cipher selection, the "dane"
security level is treated like a "mandatory" TLS security level,
@ -1357,14 +1345,14 @@ certificate must contain at least one of these names. </p>
<p> When a DANE TLSA record specifies an end-entity (EE) certificate,
(that is the actual server certificate), as with the fingerprint
security level below, no name checks or certificate expiration checks
are applied. The server certificate (or its public key) either matches
are applied. The server certificate (or its public key) either matches
the DANE record or not. Server administrators should publish such
EE records in preference to all other types. </p>
<p> The pre-requisites for DANE support in the Postfix SMTP client are: </p>
<ul>
<li> A <i>compile-time</i> OpenSSL library that supports the TLS SNI
extension and the "sha256" and "sha512" message digests.
extension and "SHA-2" message digests.
<li> A <i>compile-time</i> DNS resolver library that supports DNSSEC.
Postfix binaries built on an older system will not support DNSSEC even
if deployed on a system with an updated resolver library.
@ -2068,12 +2056,13 @@ server has a greater opportunity to mandate client security policy when
it is a dedicated MSA that only handles outbound mail from trusted clients,
below we focus on the client security policy. </p>
<p> On the SMTP client, there are further complications. When delivering
mail to a given domain, in contrast to HTTPS, one rarely uses the domain
name directly as the target host of the SMTP session. More typically,
one uses MX lookups - these are usually unauthenticated - to obtain the domain's SMTP server
hostname(s). When, as is current practice, the client verifies the
insecurely obtained MX hostname, it is subject to a DNS man-in-the-middle
<p> On the SMTP client, there are further complications. When
delivering mail to a given domain, in contrast to HTTPS, one rarely
uses the domain name directly as the target host of the SMTP session.
More typically, one uses MX lookups &mdash; these are usually
unauthenticated &mdash; to obtain the domain's SMTP server hostname(s).
When, as is current practice, the client verifies the insecurely
obtained MX hostname, it is subject to a DNS man-in-the-middle
attack. </p>
<p> Adoption of DNSSEC and <a href="http://tools.ietf.org/html/rfc6698">RFC6698</a> (DANE) may gradually (as domains
@ -2184,24 +2173,19 @@ DNSSEC. If no TLSA records are found, the effective security level
used is <a href="#client_tls_may">may</a>. If TLSA records are
found, but none are usable, the effective security level is <a
href="#client_tls_encrypt">encrypt</a>. When usable TLSA records
are obtained for the remote SMTP server, SSLv2 and SSLv3 are
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. The
<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> parameter controls optional
support for trust-anchor digest 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>
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>
<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
DNSSEC. If no TLSA records are found, or none are usable, no
connection is made to the server. When usable TLSA records are
obtained for the remote SMTP server, SSLv2 and SSLv3 are 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. The <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a>
parameter controls optional support for trust-anchor digest 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>
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>
<dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
fingerprint verification.</a> Available with Postfix 2.5 and
@ -2291,9 +2275,8 @@ Example:
/etc/postfix/tls_policy:
example.edu none
example.mil may
example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high
example.com verify
match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high
example.gov encrypt ciphers=high
example.com verify match=hostname:dot-nexthop ciphers=high
example.net secure
.example.net secure match=.example.net:example.net
[mail.example.org]:587 secure match=nexthop
@ -2407,7 +2390,7 @@ the SSL/TLS protocols used with opportunistic TLS. </p>
<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a> = aNULL
# Preferred form with Postfix &ge; 2.5:
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2
# Alternative form.
# Legacy form for Postifx &lt; 2.5:
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = SSLv3, TLSv1
# Also available with Postfix &ge; 2.6:
<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a> = export

View File

@ -410,7 +410,7 @@ examples (use only one): </p>
<blockquote>
<pre>
<a href="postconf.5.html#virtual_transport">virtual_transport</a> = <a href="lmtp.8.html">lmtp</a>:<a href="DATABASE_README.html#types">unix</a>:/path/name (uses UNIX-domain socket)
<a href="postconf.5.html#virtual_transport">virtual_transport</a> = <a href="lmtp.8.html">lmtp</a>:unix:/path/name (uses UNIX-domain socket)
<a href="postconf.5.html#virtual_transport">virtual_transport</a> = <a href="lmtp.8.html">lmtp</a>:hostname:port (uses TCP socket)
<a href="postconf.5.html#virtual_transport">virtual_transport</a> = maildrop: (uses <a href="pipe.8.html">pipe(8)</a> to command)
</pre>

View File

@ -34,16 +34,16 @@ LMDB_TABLE(5) LMDB_TABLE(5)
When a transaction fails due to a full database, Postfix
resizes the database and retries the transaction.
Postfix access, address mapping and routing tables will
generate partial search keys such as domain names without
one or more subdomains, network addresses without one or
more least-significant octets, or email addresses without
the localpart, address extension or domain portion. This
behavior is also found with <a href="DATABASE_README.html#types">btree</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="ldap_table.5.html">ldap</a>:
tables.
Postfix access, address mapping and routing table lookups
may generate partial search keys such as domain names
without one or more subdomains, network addresses without
one or more least-significant octets, or email addresses
without the localpart, address extension or domain por-
tion. This behavior is also found with <a href="DATABASE_README.html#types">btree</a>:, <a href="DATABASE_README.html#types">hash</a>:, or
<a href="ldap_table.5.html">ldap</a>: tables.
Unlike other flat-file based Postfix databases, changes to
an LMDB database do not require automatic daemon program
an LMDB database do not trigger automatic daemon program
restart.
<b>RELIABILITY</b>
@ -56,10 +56,12 @@ LMDB_TABLE(5) LMDB_TABLE(5)
The Postfix LMDB adapter implements locking with fcntl(2)
locks at whole-file granularity. LMDB's native locking
scheme would require world-writable lockfiles and would
therefore violate the Postfix security model. Unlike some
other Postfix flat-file databases, LMDB databases can
safely be updated without serializing requests through the
<a href="proxymap.8.html">proxymap(8)</a> service.
therefore violate the Postfix security model.
Multiple processes can safely update an LMDB database
without serializing requests through the <a href="proxymap.8.html">proxymap(8)</a> ser-
vice. This makes LMDB suitable as a shared cache for <a href="verify.8.html">ver-</a>
<a href="verify.8.html">ify(8)</a> or <a href="postscreen.8.html">postscreen(8)</a> services.
<b>CONFIGURATION PARAMETERS</b>
Short-lived programs automatically pick up changes to

View File

@ -598,14 +598,13 @@ SMTP(8) SMTP(8)
hostname is not an alias and its address records
lie in an unsigned zone.
<b><a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> (trust-anchor-asser-</b>
<b>tion)</b>
<b><a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> (yes)</b>
<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> trust-anchor digest support in the Postfix
TLS library.
<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 mas-
ter.cf.
The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">mas-
ter.cf</a>.
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compati-

View File

@ -609,7 +609,9 @@ LOCAL(8) LOCAL(8)
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
The set of characters that can separate a user name
from its address extension (user+foo).
from its extension (example: user+foo), or a .for-
ward file name from its extension (example: .for-
ward+foo).
<b><a href="postconf.5.html#require_home_directory">require_home_directory</a> (no)</b>
Require that a <a href="local.8.html"><b>local</b>(8)</a> recipient's home directory

View File

@ -41,12 +41,12 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5)
"inet:" followed by a hostname or address, ":", and
a port name or number. Specify an IPv6 address
inside "[]". For a UNIX-domain server specify
"<a href="DATABASE_README.html#types">unix</a>:" followed by the socket pathname. Examples:
"unix:" followed by the socket pathname. Examples:
memcache = inet:memcache.example.com:11211
memcache = inet:127.0.0.1:11211
memcache = inet:[fc00:8d00:189::3]:11211
memcache = <a href="DATABASE_README.html#types">unix</a>:/path/to/socket
memcache = unix:/path/to/socket
NOTE: to access a UNIX-domain socket with the <a href="proxymap.8.html">prox-</a>
<a href="proxymap.8.html">ymap(8)</a> server, the socket must be accessible by

View File

@ -80,10 +80,10 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
<b>MYSQL PARAMETERS</b>
<b>hosts</b> The hosts that Postfix will try to connect to and
query from. Specify <i><a href="DATABASE_README.html#types">unix</a>:</i> for UNIX domain sockets,
query from. Specify <i>unix:</i> for UNIX domain sockets,
<i>inet:</i> for TCP connections (default). Example:
hosts = host1.some.domain host2.some.domain:port
hosts = <a href="DATABASE_README.html#types">unix</a>:/file/name
hosts = unix:/file/name
The hosts are tried in random order, with all con-
nections over UNIX domain sockets being tried

View File

@ -86,10 +86,10 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
<b>PGSQL PARAMETERS</b>
<b>hosts</b> The hosts that Postfix will try to connect to and
query from. Specify <i><a href="DATABASE_README.html#types">unix</a>:</i> for UNIX-domain sockets,
query from. Specify <i>unix:</i> for UNIX-domain sockets,
<i>inet:</i> for TCP connections (default). Example:
hosts = host1.some.domain host2.some.domain:port
hosts = <a href="DATABASE_README.html#types">unix</a>:/file/name
hosts = unix:/file/name
The hosts are tried in random order, with all con-
nections over UNIX domain sockets being tried
@ -97,7 +97,7 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
matically closed after being idle for about 1
minute, and are re-opened as necessary.
NOTE: the <i><a href="DATABASE_README.html#types">unix</a>:</i> and <i>inet:</i> prefixes are accepted for
NOTE: the <i>unix:</i> and <i>inet:</i> prefixes are accepted for
backwards compatibility reasons, but are actually
ignored. The PostgreSQL client library will always
try to connect to an UNIX socket if the name starts

View File

@ -488,7 +488,9 @@ PIPE(8) PIPE(8)
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
The set of characters that can separate a user name
from its address extension (user+foo).
from its extension (example: user+foo), or a .for-
ward file name from its extension (example: .for-
ward+foo).
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.

View File

@ -15,13 +15,35 @@ POSTCONF(1) POSTCONF(1)
<b>postconf</b> [<b>-dfhnovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-C</b> <i>class,...</i>] [<i>param-</i>
<i>eter ...</i>]
<b>postconf</b> [<b>-ev</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>parameter=value ...</i>]
<b>postconf</b> [<b>-ev</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>parameter=value ...</i>
<b>postconf</b> [<b>-#vX</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>parameter ...</i>]
<b>postconf</b> [<b>-#vX</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>parameter ...</i>
<b>Managing <a href="master.5.html">master.cf</a>:</b>
<b>Managing <a href="master.5.html">master.cf</a> service entries:</b>
<b>postconf</b> [<b>-fMovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service ...</i>]
<b>postconf</b> [<b>-fMovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>] <i>...</i>]
<b>postconf</b> [<b>-eMv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type=value ...</i>
<b>postconf</b> [<b>-#MvX</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type ...</i>
<b>Managing <a href="master.5.html">master.cf</a> service fields:</b>
<b>postconf</b> [<b>-fFovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>[<b>/</b><i>field</i>]]
<i>...</i>]
<b>postconf</b> [<b>-eFv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type</i><b>/</b><i>field=value</i>
<i>...</i>
<b>Managing <a href="master.5.html">master.cf</a> service parameters:</b>
<b>postconf</b> [<b>-fPovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>[<b>/</b><i>parame-</i>
<i>ter</i>]] <i>...</i>]
<b>postconf</b> [<b>-ePv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type</i><b>/</b><i>parame-</i>
<i>ter=value ...</i>
<b>postconf</b> [<b>-PXv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type</i><b>/</b><i>parameter ...</i>
<b>Managing bounce message templates:</b>
@ -35,73 +57,73 @@ POSTCONF(1) POSTCONF(1)
By default, the <a href="postconf.1.html"><b>postconf</b>(1)</a> command displays the values of
<a href="postconf.5.html"><b>main.cf</b></a> configuration parameters, and warns about possible
mis-typed parameter names (Postfix 2.9 and later). It can
also change <a href="postconf.5.html"><b>main.cf</b></a> configuration parameter values, or
display other configuration information about the Postfix
also change <a href="postconf.5.html"><b>main.cf</b></a> configuration parameter values, or
display other configuration information about the Postfix
mail system.
Options:
<b>-a</b> List the available SASL server plug-in types. The
SASL plug-in type is selected with the
<b>-a</b> List the available SASL server plug-in types. The
SASL plug-in type is selected with the
<b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b> configuration parameter by specify-
ing one of the names listed below.
<b>cyrus</b> This server plug-in is available when Post-
<b>cyrus</b> This server plug-in is available when Post-
fix is built with Cyrus SASL support.
<b>dovecot</b>
This server plug-in uses the Dovecot authen-
tication server, and is available when Post-
fix is built with any form of SASL support.
This feature is available with Postfix 2.3 and
later.
<b>-A</b> List the available SASL client plug-in types. The
SASL plug-in type is selected with the
<b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b> or <b><a href="postconf.5.html#lmtp_sasl_type">lmtp_sasl_type</a></b> configuration
parameters by specifying one of the names listed
below.
<b>cyrus</b> This client plug-in is available when Post-
fix is built with Cyrus SASL support.
This feature is available with Postfix 2.3 and
later.
<b>-b</b> [<i>template</i><b>_</b><i>file</i>]
Display the message text that appears at the begin-
ning of delivery status notification (DSN) mes-
sages, replacing $<b>name</b> expressions with actual val-
ues as described in <a href="bounce.5.html"><b>bounce</b>(5)</a>.
To override the built-in templates, specify a tem-
plate file name at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
mand line, or specify a file name in <a href="postconf.5.html"><b>main.cf</b></a> with
the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter.
To force selection of the built-in templates, spec-
ify an empty template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a>
command line (in shell language: "").
fix is built with any form of SASL support.
This feature is available with Postfix 2.3 and
later.
<b>-A</b> List the available SASL client plug-in types. The
SASL plug-in type is selected with the
<b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b> or <b><a href="postconf.5.html#lmtp_sasl_type">lmtp_sasl_type</a></b> configuration
parameters by specifying one of the names listed
below.
<b>cyrus</b> This client plug-in is available when Post-
fix is built with Cyrus SASL support.
This feature is available with Postfix 2.3 and
later.
<b>-b</b> [<i>template</i><b>_</b><i>file</i>]
Display the message text that appears at the begin-
ning of delivery status notification (DSN) mes-
sages, replacing $<b>name</b> expressions with actual val-
ues as described in <a href="bounce.5.html"><b>bounce</b>(5)</a>.
To override the built-in templates, specify a tem-
plate file name at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
mand line, or specify a file name in <a href="postconf.5.html"><b>main.cf</b></a> with
the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter.
To force selection of the built-in templates, spec-
ify an empty template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a>
command line (in shell language: "").
This feature is available with Postfix 2.3 and
later.
<b>-c</b> <i>config</i><b>_</b><i>dir</i>
The <a href="postconf.5.html"><b>main.cf</b></a> configuration file is in the named
The <a href="postconf.5.html"><b>main.cf</b></a> configuration file is in the named
directory instead of the default configuration
directory.
<b>-C</b> <i>class,...</i>
When displaying <a href="postconf.5.html"><b>main.cf</b></a> parameters, select only
When displaying <a href="postconf.5.html"><b>main.cf</b></a> parameters, select only
parameters from the specified class(es):
<b>builtin</b>
Parameters with built-in names.
<b>service</b>
Parameters with service-defined names (the
first field of a <a href="master.5.html"><b>master.cf</b></a> entry plus a
Parameters with service-defined names (the
first field of a <a href="master.5.html"><b>master.cf</b></a> entry plus a
Postfix-defined suffix).
<b>user</b> Parameters with user-defined names.
@ -111,18 +133,41 @@ POSTCONF(1) POSTCONF(1)
The default is as if "<b>-C all</b>" is specified.
<b>-d</b> Print <a href="postconf.5.html"><b>main.cf</b></a> default parameter settings instead of
actual settings. Specify <b>-df</b> to fold long lines
actual settings. Specify <b>-df</b> to fold long lines
for human readability (Postfix 2.9 and later).
<b>-e</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and update
parameter settings with the "<i>name=value</i>" pairs on
the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line. The file is copied to
a temporary file then renamed into place. Specify
quotes to protect special characters and whitespace
on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
<b>-e</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and update
parameter settings with the "<i>name=value</i>" pairs on
the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
The <b>-e</b> is no longer needed with Postfix version 2.8
and later.
With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and
replace one or more service entries with new values
as specified with "<i>service/type=value</i>" on the <a href="postconf.1.html"><b>post-</b></a>
<a href="postconf.1.html"><b>conf</b>(1)</a> command line.
With <b>-F</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and
replace one or more service fields with new values
as specied with "<i>service/type/field=value</i>" on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line. Currently, the "command"
field contains the command name and command argu-
ments. this may change in the near future, so that
the "command" field contains only the command name,
and a new "arguments" pseudofield contains the com-
mand arguments.
With <b>-P</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and
add or update one or more service parameter set-
tings (-o parameter=value settings) with new values
as specied with "<i>service/type/parameter=value</i>" on
the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
In all cases the file is copied to a temporary file
then renamed into place. Specify quotes to protect
special characters and whitespace on the <a href="postconf.1.html"><b>post-</b></a>
<a href="postconf.1.html"><b>conf</b>(1)</a> command line.
The <b>-e</b> option is no longer needed with Postfix ver-
sion 2.8 and later.
<b>-f</b> Fold long lines when printing <a href="postconf.5.html"><b>main.cf</b></a> or <a href="master.5.html"><b>master.cf</b></a>
configuration file entries, for human readability.
@ -130,8 +175,22 @@ POSTCONF(1) POSTCONF(1)
This feature is available with Postfix 2.9 and
later.
<b>-h</b> Show <a href="postconf.5.html"><b>main.cf</b></a> parameter values without the "<i>name</i> = "
label that normally precedes the value.
<b>-F</b> Show <a href="master.5.html"><b>master.cf</b></a> per-entry field settings (by default
all services and all fields), formatted as one
"<i>service/type/field=value</i>" per line. Specify <b>-Ff</b> to
fold long lines.
Specify one or more "<i>service/type/field</i>" instances
on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line to limit the output
to fields of interest. Trailing parameter name or
service type fields that are omitted will be han-
dled as "*" wildcard fields.
This feature is available with Postfix 2.11 and
later.
<b>-h</b> Show parameter or attribute values without the
"<i>name</i> = " label that normally precedes the value.
<b>-l</b> List the names of all supported mailbox locking
methods. Postfix supports the following methods:
@ -195,15 +254,15 @@ POSTCONF(1) POSTCONF(1)
A non-shared, in-memory hash table. Its con-
tent are lost when a process terminates.
<b>ldap</b> (read-only)
LDAP database client. This is described in
<a href="ldap_table.5.html"><b>ldap_table</b>(5)</a>.
<b>lmdb</b> OpenLDAP LMDB database (a memory-mapped,
persistent file). Available on systems with
support for LMDB databases. This is
support for LMDB databases. This is
described in <a href="lmdb_table.5.html"><b>lmdb_table</b>(5)</a>.
<b>ldap</b> (read-only)
LDAP database client. This is described in
<a href="ldap_table.5.html"><b>ldap_table</b>(5)</a>.
<b>memcache</b>
Memcache database client. This is described
in <a href="memcache_table.5.html"><b>memcache_table</b>(5)</a>.
@ -213,12 +272,6 @@ POSTCONF(1) POSTCONF(1)
with support for MySQL databases. This is
described in <a href="mysql_table.5.html"><b>mysql_table</b>(5)</a>.
<b>nis</b> (read-only)
NIS client.
<b>nisplus</b> (read-only)
NIS+ client.
<b>pcre</b> (read-only)
A lookup table based on Perl Compatible Reg-
ular Expressions. The file format is
@ -274,13 +327,13 @@ POSTCONF(1) POSTCONF(1)
database. The following tables are imple-
mented:
<b><a href="DATABASE_README.html#types">unix</a>:passwd.byname</b>
<b>unix:passwd.byname</b>
The table is the UNIX password data-
base. The key is a login name. The
result is a password file entry in
<b>passwd</b>(5) format.
<b><a href="DATABASE_README.html#types">unix</a>:group.byname</b>
<b>unix:group.byname</b>
The table is the UNIX group database.
The key is a group name. The result
is a group file entry in <b>group</b>(5)
@ -293,28 +346,52 @@ POSTCONF(1) POSTCONF(1)
file contents. Specify <b>-Mf</b> to fold long lines for
human readability.
If <i>service ...</i> is specified, only the matching ser-
vices will be output. For example, "<b>postconf -Mf</b>
<b>inet</b>" will output all services that listen on the
network.
Specify zero or more arguments, each with a <i>ser-</i>
<i>vice-name</i> or <i>service-name/service-type</i> pair, where
<i>service-name</i> is the first field of a <a href="master.5.html">master.cf</a>
entry and <i>service-type</i> is one of (<b>inet</b>, <b>unix</b>, <b>fifo</b>,
or <b>pass</b>).
Specify zero or more arguments, each with a <i>ser-</i>
<i>vice-type</i> name (<b>inet</b>, <b>unix</b>, <b>fifo</b>, or <b>pass</b>) or with
a <i>service-name.service-type</i> pair, where <i>service-</i>
<i>name</i> is the first field of a <a href="master.5.html">master.cf</a> entry.
If <i>service-name</i> or <i>service-name/service-type</i> is
specified, only the matching <a href="master.5.html">master.cf</a> entries will
be output. For example, "<b>postconf -Mf smtp</b>" will
output all services named "smtp", and "<b>postconf -Mf</b>
<b>smtp/inet</b>" will output only the smtp service that
listens on the network. Trailing service type
fields that are omitted will be handled as "*"
wildcard fields.
This feature is available with Postfix 2.9 and
later.
This feature is available with Postfix 2.9 and
later. The syntax was changed from "<i>name.type</i>" to
"<i>name/type</i>", and "*" wildcard support was added
with Postfix 2.11.
<b>-n</b> Show only configuration parameters that have
explicit <i>name=value</i> settings in <a href="postconf.5.html"><b>main.cf</b></a>. Specify
<b>-n</b> Show only configuration parameters that have
explicit <i>name=value</i> settings in <a href="postconf.5.html"><b>main.cf</b></a>. Specify
<b>-nf</b> to fold long lines for human readability (Post-
fix 2.9 and later).
<b>-o</b> <i>name=value</i>
Override <a href="postconf.5.html"><b>main.cf</b></a> parameter settings.
This feature is available with Postfix 2.10 and
This feature is available with Postfix 2.10 and
later.
<b>-p</b> Show <a href="postconf.5.html"><b>main.cf</b></a> parameter settings. This is the
default.
<b>-P</b> Show <a href="master.5.html"><b>master.cf</b></a> service parameter settings (by
default all services and all parameters). format-
ted as one "<i>service/type/parameter=value</i>" per line.
Specify <b>-Pf</b> to fold long lines.
Specify one or more "<i>service/type/parameter</i>"
instances on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line to limit
the output to parameters of interest. Trailing
parameter name or service type fields that are
omitted will be handled as "*" wildcard fields.
This feature is available with Postfix 2.11 and
later.
<b>-t</b> [<i>template</i><b>_</b><i>file</i>]
@ -346,25 +423,51 @@ POSTCONF(1) POSTCONF(1)
<b>-X</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and remove the
parameters named on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
The file is copied to a temporary file then renamed
into place. Specify a list of parameter names, not
"<i>name=value</i>" pairs. There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
mand to perform the reverse operation.
Specify a list of parameter names, not "<i>name=value</i>"
pairs.
This feature is available with Postfix 2.10 and
later.
With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and
remove one or more service entries as specified
with "<i>service/type</i>" on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command
line.
With <b>-P</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and
remove one or more service parameter settings (-o
parameter=value settings) as specied with "<i>ser-</i>
<i>vice/type/parameter</i>" on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command
line.
In all cases the file is copied to a temporary file
then renamed into place. Specify quotes to protect
special characters on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the
reverse operation.
This feature is available with Postfix 2.10 and
later. Support for -M and -P was added with Post-
fix 2.11.
<b>-#</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and comment
out the parameters named on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command
line, so that those parameters revert to their
default values. The file is copied to a temporary
file then renamed into place. Specify a list of
parameter names, not "<i>name=value</i>" pairs. There is
no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse oper-
ation.
default values. Specify a list of parameter names,
not "<i>name=value</i>" pairs.
With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and
comment out one or more service entries as speci-
fied with "<i>service/type</i>" on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command
line.
In all cases the file is copied to a temporary file
then renamed into place. Specify quotes to protect
special characters on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the
reverse operation.
This feature is available with Postfix 2.6 and
later.
later. Support for -M was added with Postfix 2.11.
<b>DIAGNOSTICS</b>
Problems are reported to the standard error stream.
@ -374,41 +477,39 @@ POSTCONF(1) POSTCONF(1)
Directory with Postfix configuration files.
<b>CONFIGURATION PARAMETERS</b>
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
to this program.
The text below provides only a parameter summary. See
The text below provides only a parameter summary. See
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
Pathname of a configuration file with bounce mes-
Pathname of a configuration file with bounce mes-
sage templates.
<b>FILES</b>
/etc/postfix/<a href="postconf.5.html">main.cf</a>, Postfix configuration parameters
/etc/postfix/<a href="master.5.html">master.cf</a>, Postfix master daemon configuraton
/etc/postfix/<a href="master.5.html">master.cf</a>, Postfix master daemon configuration
<b>SEE ALSO</b>
<a href="bounce.5.html">bounce(5)</a>, bounce template file format
<a href="master.5.html">master(5)</a>, <a href="master.5.html">master.cf</a> configuration file syntax
<a href="postconf.5.html">postconf(5)</a>, <a href="postconf.5.html">main.cf</a> configuration file syntax
<a href="bounce.5.html">bounce(5)</a>, bounce template file format <a href="master.5.html">master(5)</a>, <a href="master.5.html">master.cf</a>
configuration file syntax <a href="postconf.5.html">postconf(5)</a>, <a href="postconf.5.html">main.cf</a> configuration
file syntax
<b>README FILES</b>
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
<b>LICENSE</b>
The Secure Mailer license must be distributed with this
The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
Wietse Venema
IBM T.J. Watson Research
P.O. Box 704
Yorktown Heights, NY 10598, USA
Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown
Heights, NY 10598, USA
POSTCONF(1)
</pre> </body> </html>

View File

@ -5220,7 +5220,7 @@ system. </p>
</DD>
<DT><b><a name="local_recipient_maps">local_recipient_maps</a>
(default: <a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html#types">unix</a>:passwd.byname $<a href="postconf.5.html#alias_maps">alias_maps</a>)</b></DT><DD>
(default: <a href="proxymap.8.html">proxy</a>:unix:passwd.byname $<a href="postconf.5.html#alias_maps">alias_maps</a>)</b></DT><DD>
<p> Lookup tables with all names or addresses of local recipients:
a recipient address is local when its domain matches $<a href="postconf.5.html#mydestination">mydestination</a>,
@ -8558,23 +8558,27 @@ Example:
(default: empty)</b></DT><DD>
<p> The set of characters that can separate a user name from its
address extension (user+foo). See <a href="canonical.5.html">canonical(5)</a>, <a href="local.8.html">local(8)</a>, <a href="relocated.5.html">relocated(5)</a>
and <a href="virtual.5.html">virtual(5)</a> for the effects this has on aliases, canonical,
virtual, and relocated lookups. Basically, the software tries
user+foo and .forward+foo before trying user and .forward. </p>
<p> This implementation recognizes one delimiter character per email
address, and one address extension per email address. </p>
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo). Basically, the software tries
user+foo and .forward+foo before trying user and .forward. This
implementation recognizes one delimiter character and one extension
per email address or .forward file name. </p>
<p> When the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> set contains multiple characters
(Postfix 2.11 and later), a user name is separated from its address
extension by the first character that matches the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>
set. </p>
(Postfix 2.11 and later), a user name or .forward file name is
separated from its extension by the first character that matches
the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> set. </p>
<p> See <a href="canonical.5.html">canonical(5)</a>, <a href="local.8.html">local(8)</a>, <a href="relocated.5.html">relocated(5)</a> and <a href="virtual.5.html">virtual(5)</a> for the
effects of <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> on lookups in aliases, canonical,
virtual, and relocated maps, and see the <a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a>
parameter for propagating an extension from one email address to
another. </p>
<p> When used in <a href="postconf.5.html#command_execution_directory">command_execution_directory</a>, <a href="postconf.5.html#forward_path">forward_path</a>, or
<a href="postconf.5.html#luser_relay">luser_relay</a>, ${<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>} is replaced
with the recipient delimiter that was found in the recipient email
address (Postfix 2.11 and later), or it is replaced with the <a href="postconf.5.html">main.cf</a>
<a href="postconf.5.html#luser_relay">luser_relay</a>, ${<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a>} is replaced with the actual
recipient delimiter that was found in the recipient email address
(Postfix 2.11 and later), or it is replaced with the <a href="postconf.5.html">main.cf</a>
<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> parameter value (Postfix 2.10 and earlier).
</p>
@ -9550,7 +9554,7 @@ IP address),
transport map,
<li> if mail is sent via a UNIX-domain socket: a pathname (without
the <a href="DATABASE_README.html#types">unix</a>: prefix),
the unix: prefix),
<li> a /file/name with domain names and/or <a href="postconf.5.html#relayhost">relay host</a> names as
defined above,
@ -11479,6 +11483,35 @@ whitespace, commas or colons. In the policy table "protocols" attribute
empty value means allow all protocols. The valid protocol names, (see
<b>SSL_get_version(3)</b>), are "SSLv2", "SSLv3" and "TLSv1". </p>
<p> With Postfix &ge; 2.5 the parameter syntax was expanded to support
protocol exclusions. One can explicitly exclude "SSLv2" by setting
"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2". To exclude both "SSLv2" and
"SSLv3" set "<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the underlying OpenSSL interface semantics.
</p>
<p> The range of protocols advertised by an SSL/TLS client must be
contiguous. When a protocol version is enabled, disabling any
higher version implicitly disables all versions above that higher
version. Thus, for example: </p>
<blockquote>
<pre>
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !TLSv1
</pre>
</blockquote>
<p> also disables any protocols version higher than TLSv1 leaving
only "SSLv3" enabled. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". When Postfix &le; 2.5 is linked against OpenSSL 1.0.1
or later, these, or any other new protocol versions, cannot be
disabled except by also disabling "TLSv1" (typically leaving just
"SSLv3"). The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can explicitly disable support for
"TLSv1.1" or "TLSv1.2". </p>
<p> At the <a href="TLS_README.html#client_tls_dane">dane</a> and
<a href="TLS_README.html#client_tls_dane">dane-only</a> security
levels, when usable TLSA records are obtained for the remote SMTP
@ -11486,24 +11519,10 @@ server, the Postfix SMTP client is obligated to include the SNI TLS
extension in its SSL client hello message. This may help the remote
SMTP server live up to its promise to provide a certificate that
matches its TLSA records. Since TLS extensions require TLS 1.0 or
later, the Postfix SMTP client must disable SSLv2 and SSLv3 when
later, the Postfix SMTP client must disable "SSLv2" and "SSLv3" when
SNI is required. If you use "dane" or "dane-only" do not disable
TLSv1, except perhaps via the policy table for destinations which
you are sure will support TLSv1.1 or TLSv1.2. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
<p> With Postfix &ge; 2.5 the parameter syntax is expanded to support
protocol exclusions. One can now explicitly exclude SSLv2 by setting
"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2". To exclude both SSLv2 and
SSLv3 set "<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the behavior when the OpenSSL library is newer than Postfix.
</p>
you are sure will support "TLSv1.1" or "TLSv1.2". </p>
<p> Since SSL version 2 has known protocol weaknesses and is now
deprecated, the default setting excludes "SSLv2". This means that by
@ -11516,9 +11535,9 @@ and higher. </p>
<p> Example: </p>
<pre>
# Preferred form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = TLSv1
</pre>
@ -11637,7 +11656,7 @@ which is either the recipient domain, or the verbatim next-hop
specified in the transport table, $<a href="postconf.5.html#local_transport">local_transport</a>, $<a href="postconf.5.html#virtual_transport">virtual_transport</a>,
$<a href="postconf.5.html#relay_transport">relay_transport</a> or $<a href="postconf.5.html#default_transport">default_transport</a>. This includes any enclosing
square brackets and any non-default destination server port suffix. The
LMTP socket type prefix (inet: or <a href="DATABASE_README.html#types">unix</a>:) is not included in the lookup
LMTP socket type prefix (inet: or unix:) is not included in the lookup
key. </p>
<p> Only the next-hop domain, or $<a href="postconf.5.html#myhostname">myhostname</a> with LMTP over UNIX-domain
@ -11690,23 +11709,17 @@ the effective security level used is <a
href="TLS_README.html#client_tls_may">may</a>. If TLSA records are
found, but none are usable, the effective security level is <a
href="TLS_README.html#client_tls_encrypt">encrypt</a>. When usable
TLSA records are obtained for the remote SMTP server, SSLv2 and
SSLv3 are 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. The
<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> parameter controls optional
support for trust-anchor digest 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>
TLSA records are obtained for the remote SMTP server, 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>
<dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt>
<dd>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 connection is made to the server. When
usable TLSA records are obtained for the remote SMTP server, SSLv2
and SSLv3 are 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. The
<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> parameter controls optional
support for trust-anchor digest TLSA records. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS
usable TLSA records are obtained for the remote SMTP server, 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>
@ -11807,22 +11820,34 @@ separator is colon. An empty value means allow all protocols. The valid
protocol names, (see <b>SSL_get_version(3)</b>), are "SSLv2", "SSLv3"
and "TLSv1". </p>
<p> The range of protocols advertised by an SSL/TLS client must be
contiguous. When a protocol version is enabled, disabling any
higher version implicitly disables all versions above that higher
version. Thus, for example: </p>
<blockquote>
<pre>
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2, !TLSv1
</pre>
</blockquote>
<p> also disables any protocols version higher than TLSv1 leaving
only "SSLv3" enabled. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
and "TLSv1.2". The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can explicitly disable support for
"TLSv1.1" or "TLSv1.2"</p>
<p> To include a protocol list its name, to exclude it, prefix the name
with a "!" character. To exclude SSLv2 even for opportunistic TLS set
"<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> = !SSLv2". To exclude both "SSLv2" and "SSLv3" set
"<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> = !SSLv2, !SSLv3". Explicitly listing the protocols to
include, rather than protocols to exclude, is supported, but not
recommended. The exclusion form more closely matches the behavior
when the OpenSSL library is newer than Postfix. </p>
recommended. The exclusion form more closely matches the underlying
OpenSSL interface semantics. </p>
<p> Example: </p>
<pre>
# TLSv1 only!
# TLSv1 or better:
<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> = !SSLv2, !SSLv3
</pre>
@ -11955,20 +11980,17 @@ parameter. When TLSA records are not found or are all unusable the
effective security level is "may" or "encrypt" respectively. For
purposes of protocol and cipher selection, the "dane" security level
is treated like a "mandatory" TLS security level, and weak ciphers
and protocols are disabled. SSLv2 and SSLv3 are automatically
disabled when usable TLSA records are obtained for the remote SMTP
server, see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> for details. Since DANE
authenticates server certificates the "aNULL" cipher-suites are
transparently excluded at this level, no need to configure this
manually. The <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> <a href="postconf.5.html">main.cf</a> parameter
controls optional support for trust-anchor digest TLSA records.
<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication is available with Postfix 2.11
and later. </dd>
and protocols are disabled. Since DANE authenticates server
certificates the "aNULL" cipher-suites are transparently excluded
at this level, no need to configure this manually. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE)
TLS authentication is available with Postfix 2.11 and later. </dd>
<dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt>
<dd>Mandatory DANE TLS. This is just like "dane" above, only DANE
TLSA authentication is mandatory. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication
is available with Postfix 2.11 and later. </dd>
<dd>Mandatory DANE TLS. This is just like "dane" above, but DANE
TLSA authentication is required. There is no fallback to "may" or
"encrypt" when TLSA records are missing or unusable. <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>
(DANE) TLS authentication is available with Postfix 2.11 and later.
</dd>
<dt><b><a href="TLS_README.html#client_tls_fingerprint">fingerprint</a></b></dt>
<dd>Certificate fingerprint verification.
@ -13785,7 +13807,7 @@ supposed to give the result to another Postfix SMTP server process.
</p>
<p> Specify "host:port" or "inet:host:port" for a TCP endpoint, or
"<a href="DATABASE_README.html#types">unix</a>:pathname" for a UNIX-domain endpoint. The host can be specified
"unix:pathname" for a UNIX-domain endpoint. The host can be specified
as an IP address or as a symbolic name; no MX lookups are done.
When no "host" or "host:" are specified, the local machine is
assumed. Pathname interpretation is relative to the Postfix queue
@ -13793,7 +13815,7 @@ directory. </p>
<p> This feature is available in Postfix 2.1 and later. </p>
<p> The "inet:" and "<a href="DATABASE_README.html#types">unix</a>:" prefixes are available in Postfix 2.3
<p> The "inet:" and "unix:" prefixes are available in Postfix 2.3
and later. </p>
@ -15615,25 +15637,26 @@ works in addition to the exclusions listed with <a href="postconf.5.html#smtpd_t
(default: !SSLv2)</b></DT><DD>
<p> The SSL/TLS protocols accepted by the Postfix SMTP server with
mandatory TLS encryption. If the list is empty, the server supports all
available SSL/TLS protocol versions. A non-empty value is a list
of protocol
names separated by whitespace, commas or colons. The supported protocol
names are "SSLv2", "SSLv3" and "TLSv1", and are not case sensitive. </p>
mandatory TLS encryption. If the list is empty, the server supports
all available SSL/TLS protocol versions. A non-empty value is a
list of protocol names separated by whitespace, commas or colons.
The supported protocol names are "SSLv2", "SSLv3" and "TLSv1", and
are not case sensitive. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
<p> With Postfix &ge; 2.5 the parameter syntax is expanded to support
protocol exclusions. One can now explicitly exclude SSLv2 by setting
"<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = !SSLv2". To exclude both SSLv2 and
SSLv3 set "<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = !SSLv2, !SSLv3". Listing
<p> With Postfix &ge; 2.5 the parameter syntax was expanded to support
protocol exclusions. One can explicitly exclude "SSLv2" by setting
"<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = !SSLv2". To exclude both "SSLv2" and
"SSLv3" set "<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the behavior when the OpenSSL library is newer than Postfix.
</p>
matches the underlying OpenSSL interface semantics. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". When Postfix &le; 2.5 is linked against OpenSSL 1.0.1
or later, these, or any other new protocol versions, cannot be
disabled. The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can disable support for "TLSv1.1" or
"TLSv1.2". </p>
<p> Since SSL version 2 has known protocol weaknesses and is now
deprecated, the default setting excludes "SSLv2". This means that
@ -15643,9 +15666,10 @@ level. </p>
<p> Example: </p>
<pre>
<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = TLSv1
# Alternative form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = !SSLv2, !SSLv3
# Legacy syntax:
<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> = TLSv1
</pre>
<p> This feature is available in Postfix 2.3 and later. </p>
@ -15657,28 +15681,25 @@ level. </p>
(default: empty)</b></DT><DD>
<p> List of TLS protocols that the Postfix SMTP server will exclude
or include with opportunistic TLS encryption. This parameter SHOULD be
left at its default empty value, allowing all protocols to be used with
opportunistic TLS. </p>
<p> In <a href="postconf.5.html">main.cf</a> the values are separated by whitespace, commas or
colons. An empty value means allow all protocols. The valid protocol
names, (see <b>SSL_get_version(3)</b>), are "SSLv2", "SSLv3" and
"TLSv1". In <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> table entries, "protocols" attribute
values are separated by a colon. </p>
or include with opportunistic TLS encryption. This parameter SHOULD
be left at its default empty value, allowing all protocols to be
used with opportunistic TLS. A non-empty value is a list of protocol
names separated by whitespace, commas or colons. The supported
protocol names are "SSLv2", "SSLv3" and "TLSv1", and are not case
sensitive. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
and "TLSv1.2". The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can disable support for "TLSv1.1" or
"TLSv1.2". </p>
<p> To include a protocol list its name, to exclude it, prefix the name
with a "!" character. To exclude SSLv2 even for opportunistic TLS set
"<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> = !SSLv2". To exclude both "SSLv2" and "SSLv3" set
"<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> = !SSLv2, !SSLv3". Explicitly listing the protocols to
include, rather than protocols to exclude, is supported, but not
recommended. The exclusion form more closely matches the behavior
when the OpenSSL library is newer than Postfix. </p>
recommended. The exclusion form more closely matches the underlying
OpenSSL interface semantics. </p>
<p> Example: </p>
<pre>
@ -16212,6 +16233,70 @@ bytes (equivalent to 256 bits) is sufficient to generate a 128bit
<p> This feature is available in Postfix 2.2 and later. </p>
</DD>
<DT><b><a name="tls_dane_digest_agility">tls_dane_digest_agility</a>
(default: on)</b></DT><DD>
<p> Configure DANE TLSA digest algorithm agility. When digest
algorithm agility is enabled, and the server and client support a
common strong digest algorithm, TLSA records with weaker digest
algorithms are ignored. </p>
<p> Specify one of the following: </p>
<dl>
<dt><b>off</b></dt>
<dd> DANE verification examines each well-formed record in the TLSA
RRset whose matching type is either "0" (no hash used) or is one of
the digest algorithms listed in $<a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a>. This setting
is not recommended. </dd>
<dt><b>on</b></dt>
<dd> From each group of well-formed TLSA RRs a non-zero digest
matching type with the same certificate usage and selector, DANE
verification examines only those records whose matching type has
the highest precedence (appear earliest in $<a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a>).
</dd>
<dt><b>maybe</b></dt>
<dd> For compatibility with digest algorithm agility, each certificate
or public key whose digest is included in a DANE TLSA RRset, SHOULD
be published with the same set of digest matching type values as
any other with the same usage and selector. Therefore, compatible
TLSA RRsets will contain an identical count of well-formed RRs with
each non-zero digest matching type for any fixed combination of
usage and selector. When this constraint is violated, or any of
the digest records are malformed, digest algorithm agility will
disabled. Otherwise, digest algorithm agility is enabled. </dd>
</dl>
<p> Digest algorithm agility ensures that the strongest digest
supported by both the Postfix SMTP client and the remote server is
used, and weaker digests are ignored. This supports non-disruptive
deprecation of outdated digest algorithms. </p>
<p> To ensure compatibility with digest algorithm agility during
key rotation, when a certificate or public key is being replaced
with another, and both are published during the transition, both
the old and the new certificate MUST be specified with the same set
of digests. One can change the list of digest algorithms later,
once old keys are retired. At any given time, change either the
list of digests without changing the list of certificates or public
keys or the list of certificates or public keys without changing
the list of digests. Full value matching type "0" records are not
subject to this constraint, but are discouraged due to the size of
the resulting DNS records. </p>
<p> It is expected that this algorithm agility mechanism will be
published in a standards track RFC for SMTP with DANE, and also in
an eventual update to <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>. </p>
<p> This feature is available in Postfix 2.11 and later. </p>
</DD>
<DT><b><a name="tls_dane_digests">tls_dane_digests</a>
@ -16220,85 +16305,58 @@ bytes (equivalent to 256 bits) is sufficient to generate a 128bit
<p> <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> TLSA resource-record "matching type" digest algorithms
in descending preference order. All the specified algorithms must
be supported by the underlying OpenSSL library, otherwise the Postfix
SMTP client will not support DANE TLSA security. </p>
SMTP client will not support DANE TLSA security. </p>
<p> Specify a list of digest names separated by commas and/or
whitespace. Each digest name may be followed by an optional
"=&lt;number&gt;" suffix. For example, "sha512" may instead be specified
as "sha512=2" and "sha256" may instead be specified as "sha256=1".
The optional number must match the <a
href="https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml#matching-types"
>IANA</a> assigned TLSA matching type number the algorithm in question.
Postfix will check this constraint for the algorithms it knows about.
Additional matching type algorithms registered with IANA can be added
with explicit numbers provided they are supported by OpenSSL. </p>
<p> Invalid list elements are logged with a warning and disable DANE
support. TLSA RRs that specify digests not included in the list are
ignored with a warning. </p>
<p> Note: It is unwise to omit sha256 from the digest list. This
digest algorithm is the only mandatory to implement digest algorithm
in <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>, and many servers are expected publish TLSA records
with just sha256 digests. Unless one of the standard digests is
seriously compromised and servers have had ample time to update their
TLSA records you should not omit any standard digests, just arrange
them in order from strongest to weakest. </p>
<p> When for a particular combination of "certificate usage" and
"selector" the TLSA RRset contains a well-formed record with a
matching type of "0", i.e. a full value of the associated certificate
or public key, the Postfix SMTP client will ignore all other matching
types for the same certificate usage and selector. In this case
the first algorithm listed in <a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a> will be used to
compute a digest of the full value, which will then be used to match
certificates or public keys in the server's certificate chain. </p>
"selector" the TLSA RRset contains records with more than one digest
matching type, the tls_dane_digest_agility parameter determines
whether all the RRs are used, or only those with the most preferred
digest matching type. </p>
<p> Otherwise, when for a particular combination of "certificate
usage" and "selector" the TLSA RRset contains a records with more
than one non-zero matching type, i.e. multiple digest algorithms,
only records with the highest preference digest are used after
discarding any records with an incorrect digest length as unusable. </p>
<p> The <a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> parameter controls
whether any digest TLSA records are acceptable in usage "2" (trust
anchor assertion) TLSA records. </p>
<p> This strategy ensures that the strongest digest supported by
both the Postfix SMTP client and the remote server is used, and
weaker digests are ignored. This supports non-disruptive deprecation
of outdated digest algorithms. </p>
<p> The strategy requires that when a TLSA RRset provides association
data for multiple certificates or public keys, all RRs with the same
"certificate usage" and "selector" be published with the same set
of digests. In particular, during key rotation, when a certificate
or public key is being replaced with another (and both are published
during the transition) both the old and the new certificate MUST be
specified with the same set of digests. One can change the list of
digest algorithms later, once old keys are retired. At any given
time change either the list of digests without changing the list of
certificates or public keys or the list of certificates or public
keys without changing the list of digests. </p>
<p> It is expected that this algorithm agility mechanism will be
published in a standards track RFC for SMTP with DANE, and perhaps
in an eventual update to <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a>. </p>
<p> This feature is available in Postfix 2.11. </p>
<p> This feature is available in Postfix 2.11 and later. </p>
</DD>
<DT><b><a name="tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a>
(default: trust-anchor-assertion)</b></DT><DD>
(default: yes)</b></DT><DD>
<p> <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> trust-anchor digest support in the Postfix TLS library.
Specify zero or more of the following options, separated by comma or
whitespace. Option names are case-insensitive. </p>
<dl>
<dt><b>ca-constraint</b></dt>
<dd> Enable support for <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE TLSA) DNS records that
contain digests of trust-anchors with certificate usage "0".
These are often public root CAs, and server operators may
expect that clients will have the corresponding root certificate
in their CAfile or CApath. Most SSL/TLS servers do not send public
root CA certificate in their certificate chain, so if Postfix does
not have the CA certificate locally, there is no way to associate
the digest with the trust chain from the server. These TLSA records
are fragile, and only work when you have a complete (whatever that
means) set of public CAs in your CAfile or CApath. Enable this
with caution if at all. </dd>
<dt><b>trust-anchor-assertion</b></dt>
<dd> Enable support for <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE TLSA) DNS records that contain
Enable support for <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE TLSA) DNS records that contain
digests of trust-anchors with certificate usage "2". In this case
the certificate usage logically requires the server administrator
to configure the server to include the trust-anchor certificate in
the server's SSL certificate chain. These TLSA records are less
fragile than "ca-constraint" TLSA records, and are enabled by
default. Having a "complete" CAfile or CApath does not help in
this case, you are at the mercy of the remote server administrator's
competence. </dd>
</dl>
the server's SSL certificate chain. If enough domains mess this
up, you can disable support for these TLSA records, but you'll no
longer have secure connections that get it right and only publish
trust anchor records. </p>
<p> At the <a href="TLS_README.html#client_tls_dane">dane</a>
security level, when a TLSA RRset includes only unusable associations,
@ -16309,6 +16367,11 @@ href="TLS_README.html#client_tls_dane">dane-only</a> security level,
the server in question is skipped and delivery is deferred if no
secure servers are found. </p>
<p> The <a href="postconf.5.html#tls_dane_digests">tls_dane_digests</a> parameter controls the list of digest
algorithms that are supported in TLSA records. The tls_dane_digest_agility
parameter controls digest algorithm downgrade attack resistance.
</p>
<p> This feature is available in Postfix 2.11 and later. </p>
@ -16572,7 +16635,11 @@ or performant cipher choice, there is some risk of interoperability
issues. In the past, some SSL clients have listed lower priority ciphers
that they did not implement correctly. If the server chooses a cipher
that the client prefers less, it may select a cipher whose client
implementation is flawed. </p>
implementation is flawed. Most notably Windows 2003 Microsoft
Exchange servers have flawed implementations of DES-CBC3-SHA, which
OpenSSL considers stronger than RC4-SHA. Enabling server cipher-suite
selection may create interoperability issues with Windows 2003
Microsoft Exchange clients. </p>
<p> This feature is available in Postfix 2.8 and later, in combination
with OpenSSL 0.9.7 and later. </p>

View File

@ -598,14 +598,13 @@ SMTP(8) SMTP(8)
hostname is not an alias and its address records
lie in an unsigned zone.
<b><a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> (trust-anchor-asser-</b>
<b>tion)</b>
<b><a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">tls_dane_trust_anchor_digest_enable</a> (yes)</b>
<a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> trust-anchor digest support in the Postfix
TLS library.
<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 mas-
ter.cf.
The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">mas-
ter.cf</a>.
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compati-

View File

@ -1287,7 +1287,9 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
The set of characters that can separate a user name
from its address extension (user+foo).
from its extension (example: user+foo), or a .for-
ward file name from its extension (example: .for-
ward+foo).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
The text that follows the 220 status code in the

View File

@ -11,10 +11,10 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5)
<b>SYNOPSIS</b>
<b>postmap -q "</b><i>string</i><b>" <a href="socketmap_table.html">socketmap</a>:inet:</b><i>host</i><b>:</b><i>port</i><b>:</b><i>name</i>
<b>postmap -q "</b><i>string</i><b>" <a href="socketmap_table.html">socketmap</a>:<a href="DATABASE_README.html#types">unix</a>:</b><i>pathname</i><b>:</b><i>name</i>
<b>postmap -q "</b><i>string</i><b>" <a href="socketmap_table.html">socketmap</a>:unix:</b><i>pathname</i><b>:</b><i>name</i>
<b>postmap -q - <a href="socketmap_table.html">socketmap</a>:inet:</b><i>host</i><b>:</b><i>port</i><b>:</b><i>name</i> &lt;<i>inputfile</i>
<b>postmap -q - <a href="socketmap_table.html">socketmap</a>:<a href="DATABASE_README.html#types">unix</a>:</b><i>pathname</i><b>:</b><i>name</i> &lt;<i>inputfile</i>
<b>postmap -q - <a href="socketmap_table.html">socketmap</a>:unix:</b><i>pathname</i><b>:</b><i>name</i> &lt;<i>inputfile</i>
<b>DESCRIPTION</b>
The Postfix mail system uses optional tables for address
@ -22,7 +22,7 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5)
The Postfix socketmap client expects TCP endpoint names of
the form <b>inet:</b><i>host</i><b>:</b><i>port</i><b>:</b><i>name</i>, or UNIX-domain endponts of
the form <b><a href="DATABASE_README.html#types">unix</a>:</b><i>pathname</i><b>:</b><i>name</i>. In both cases, <i>name</i> speci-
the form <b>unix:</b><i>pathname</i><b>:</b><i>name</i>. In both cases, <i>name</i> speci-
fies the name field in a socketmap client request (see
"REQUEST FORMAT" below).

View File

@ -138,7 +138,9 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
The set of characters that can separate a user name
from its address extension (user+foo).
from its extension (example: user+foo), or a .for-
ward file name from its extension (example: .for-
ward+foo).
<b><a href="postconf.5.html#swap_bangpath">swap_bangpath</a> (yes)</b>
Enable the rewriting of "site!user" into

View File

@ -201,7 +201,7 @@ case "$SYSTEM.$RELEASE" in
;;
SunOS.5*) SYSTYPE=SUNOS5
RANLIB=echo
SYSLIBS="-lresolv -lsocket -lnsl"
SYSLIBS="-lresolv -lsocket -lnsl -ldl"
# Stock awk breaks with >10 files.
test -x /usr/xpg4/bin/awk && AWK=/usr/xpg4/bin/awk
# Solaris 2.5 added usleep(), POSIX regexp, POSIX getpwnam/uid_r

View File

@ -15,15 +15,40 @@ Postfix configuration utility
[\fB-C \fIclass,...\fR] [\fIparameter ...\fR]
\fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
[\fIparameter=value ...\fR]
\fIparameter=value ...\fR
\fBpostconf\fR [\fB-#vX\fR] [\fB-c \fIconfig_dir\fR]
[\fIparameter ...\fR]
\fIparameter ...\fR
\fBManaging master.cf:\fR
\fBManaging master.cf service entries:\fR
\fBpostconf\fR [\fB-fMovx\fR] [\fB-c \fIconfig_dir\fR]
[\fIservice ...\fR]
[\fIservice\fR[\fB/\fItype\fR]\fI ...\fR]
\fBpostconf\fR [\fB-eMv\fR] [\fB-c \fIconfig_dir\fR]
\fIservice\fB/\fItype=value ...\fR
\fBpostconf\fR [\fB-#MvX\fR] [\fB-c \fIconfig_dir\fR]
\fIservice\fB/\fItype ...\fR
\fBManaging master.cf service fields:\fR
\fBpostconf\fR [\fB-fFovx\fR] [\fB-c \fIconfig_dir\fR]
[\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR]
\fBpostconf\fR [\fB-eFv\fR] [\fB-c \fIconfig_dir\fR]
\fIservice\fB/\fItype\fB/\fIfield=value ...\fR
\fBManaging master.cf service parameters:\fR
\fBpostconf\fR [\fB-fPovx\fR] [\fB-c \fIconfig_dir\fR]
[\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR]
\fBpostconf\fR [\fB-ePv\fR] [\fB-c \fIconfig_dir\fR]
\fIservice\fB/\fItype\fB/\fIparameter=value ...\fR
\fBpostconf\fR [\fB-PXv\fR] [\fB-c \fIconfig_dir\fR]
\fIservice\fB/\fItype\fB/\fIparameter ...\fR
\fBManaging bounce message templates:\fR
@ -114,21 +139,56 @@ Specify \fB-df\fR to fold long lines for human readability
(Postfix 2.9 and later).
.IP \fB-e\fR
Edit the \fBmain.cf\fR configuration file, and update
parameter settings with the "\fIname=value\fR" pairs
on the \fBpostconf\fR(1) command line. The file is copied
to a temporary file then renamed into place.
Specify quotes to protect special characters and whitespace
on the \fBpostconf\fR(1) command line.
parameter settings with the "\fIname=value\fR" pairs on the
\fBpostconf\fR(1) command line.
The \fB-e\fR is no longer needed with Postfix version 2.8
and later.
With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
and replace one or more service entries with new values as
specified with "\fIservice/type=value\fR" on the \fBpostconf\fR(1)
command line.
With \fB-F\fR, edit the \fBmaster.cf\fR configuration file,
and replace one or more service fields with new values as
specied with "\fIservice/type/field=value\fR" on the
\fBpostconf\fR(1) command line. Currently, the "command"
field contains the command name and command arguments. this
may change in the near future, so that the "command" field
contains only the command name, and a new "arguments"
pseudofield contains the command arguments.
With \fB-P\fR, edit the \fBmaster.cf\fR configuration file,
and add or update one or more service parameter settings
(-o parameter=value settings) with new values as specied
with "\fIservice/type/parameter=value\fR" on the \fBpostconf\fR(1)
command line.
In all cases the file is copied to a temporary file then
renamed into place. Specify quotes to protect special
characters and whitespace on the \fBpostconf\fR(1) command
line.
The \fB-e\fR option is no longer needed with Postfix version
2.8 and later.
.IP \fB-f\fR
Fold long lines when printing \fBmain.cf\fR or \fBmaster.cf\fR
configuration file entries, for human readability.
This feature is available with Postfix 2.9 and later.
.IP \fB-F\fR
Show \fBmaster.cf\fR per-entry field settings (by default
all services and all fields), formatted as one
"\fIservice/type/field=value\fR" per line. Specify \fB-Ff\fR
to fold long lines.
Specify one or more "\fIservice/type/field\fR" instances
on the \fBpostconf\fR(1) command line to limit the output
to fields of interest. Trailing parameter name or service
type fields that are omitted will be handled as "*" wildcard
fields.
This feature is available with Postfix 2.11 and later.
.IP \fB-h\fR
Show \fBmain.cf\fR parameter values without the "\fIname\fR
Show parameter or attribute values without the "\fIname\fR
= " label that normally precedes the value.
.IP \fB-l\fR
List the names of all supported mailbox locking methods.
@ -139,21 +199,22 @@ A kernel-based advisory locking method for local files only.
This locking method is available on systems with a BSD
compatible library.
.IP \fBfcntl\fR
A kernel-based advisory locking method for local and remote files.
A kernel-based advisory locking method for local and remote
files.
.IP \fBdotlock\fR
An application-level locking method. An application locks a file
named \fIfilename\fR by creating a file named \fIfilename\fB.lock\fR.
The application is expected to remove its own lock file, as well as
stale lock files that were left behind after abnormal program
termination.
An application-level locking method. An application locks
a file named \fIfilename\fR by creating a file named
\fIfilename\fB.lock\fR. The application is expected to
remove its own lock file, as well as stale lock files that
were left behind after abnormal program termination.
.RE
.IP \fB-m\fR
List the names of all supported lookup table types. In Postfix
configuration files,
lookup tables are specified as \fItype\fB:\fIname\fR, where
\fItype\fR is one of the types listed below. The table \fIname\fR
syntax depends on the lookup table type as described in the
DATABASE_README document.
List the names of all supported lookup table types. In
Postfix configuration files, lookup tables are specified
as \fItype\fB:\fIname\fR, where \fItype\fR is one of the
types listed below. The table \fIname\fR syntax depends on
the lookup table type as described in the DATABASE_README
document.
.RS
.IP \fBbtree\fR
A sorted, balanced tree structure. Available on systems
@ -181,22 +242,18 @@ with support for Berkeley DB databases.
.IP \fBinternal\fR
A non-shared, in-memory hash table. Its content are lost
when a process terminates.
.IP "\fBldap\fR (read-only)"
LDAP database client. This is described in \fBldap_table\fR(5).
.IP "\fBlmdb\fR"
OpenLDAP LMDB database (a memory-mapped, persistent file).
Available on systems with support for LMDB databases. This
is described in \fBlmdb_table\fR(5).
.IP "\fBldap\fR (read-only)"
LDAP database client. This is described in \fBldap_table\fR(5).
.IP "\fBmemcache\fR"
Memcache database client. This is described in
\fBmemcache_table\fR(5).
.IP "\fBmysql\fR (read-only)"
MySQL database client. Available on systems with support
for MySQL databases. This is described in \fBmysql_table\fR(5).
.IP "\fBnis\fR (read-only)"
NIS client.
.IP "\fBnisplus\fR (read-only)"
NIS+ client.
.IP "\fBpcre\fR (read-only)"
A lookup table based on Perl Compatible Regular Expressions.
The file format is described in \fBpcre_table\fR(5).
@ -220,53 +277,78 @@ UNIX-domain server. This is described in \fBsocketmap_table\fR(5).
.IP "\fBsqlite\fR (read-only)"
SQLite database. This is described in \fBsqlite_table\fR(5).
.IP "\fBstatic\fR (read-only)"
A table that always returns its name as lookup result. For example,
\fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup
result.
A table that always returns its name as lookup result. For
example, \fBstatic:foobar\fR always returns the string
\fBfoobar\fR as lookup result.
.IP "\fBtcp\fR (read-only)"
TCP/IP client. The protocol is described in \fBtcp_table\fR(5).
.IP "\fBtexthash\fR (read-only)"
Produces similar results as hash: files, except that you don't
need to run the \fBpostmap\fR(1) command before you can use the file,
and that it does not detect changes after the file is read.
Produces similar results as hash: files, except that you
don't need to run the \fBpostmap\fR(1) command before you
can use the file, and that it does not detect changes after
the file is read.
.IP "\fBunix\fR (read-only)"
A limited view of the UNIX authentication database. The
following tables are implemented:
.RS
. IP \fBunix:passwd.byname\fR
The table is the UNIX password database. The key is a login name.
The result is a password file entry in \fBpasswd\fR(5) format.
The table is the UNIX password database. The key is a login
name. The result is a password file entry in \fBpasswd\fR(5)
format.
.IP \fBunix:group.byname\fR
The table is the UNIX group database. The key is a group name.
The result is a group file entry in \fBgroup\fR(5) format.
The table is the UNIX group database. The key is a group
name. The result is a group file entry in \fBgroup\fR(5)
format.
.RE
.RE
.IP
Other table types may exist depending on how Postfix was built.
Other table types may exist depending on how Postfix was
built.
.IP \fB-M\fR
Show \fBmaster.cf\fR file contents instead of \fBmain.cf\fR
file contents.
Specify \fB-Mf\fR to fold long lines for human readability.
file contents. Specify \fB-Mf\fR to fold long lines for
human readability.
If \fIservice ...\fR is specified, only the matching services
will be output. For example, "\fBpostconf -Mf inet\fR"
will output all services that listen on the network.
Specify zero or more arguments, each with a \fIservice-name\fR
or \fIservice-name/service-type\fR pair, where \fIservice-name\fR
is the first field of a master.cf entry and \fIservice-type\fR
is one of (\fBinet\fR, \fBunix\fR, \fBfifo\fR, or \fBpass\fR).
Specify zero or more arguments, each with a \fIservice-type\fR
name (\fBinet\fR, \fBunix\fR, \fBfifo\fR, or \fBpass\fR)
or with a \fIservice-name.service-type\fR pair, where
\fIservice-name\fR is the first field of a master.cf entry.
If \fIservice-name\fR or \fIservice-name/service-type\fR
is specified, only the matching master.cf entries will be
output. For example, "\fBpostconf -Mf smtp\fR" will output
all services named "smtp", and "\fBpostconf -Mf smtp/inet\fR"
will output only the smtp service that listens on the
network. Trailing service type fields that are omitted
will be handled as "*" wildcard fields.
This feature is available with Postfix 2.9 and later.
This feature is available with Postfix 2.9 and later. The
syntax was changed from "\fIname.type\fR" to "\fIname/type\fR",
and "*" wildcard support was added with Postfix 2.11.
.IP \fB-n\fR
Show only configuration parameters that have explicit
\fIname=value\fR settings in \fBmain.cf\fR.
Specify \fB-nf\fR to fold long lines for human readability
(Postfix 2.9 and later).
\fIname=value\fR settings in \fBmain.cf\fR. Specify \fB-nf\fR
to fold long lines for human readability (Postfix 2.9 and
later).
.IP "\fB-o \fIname=value\fR"
Override \fBmain.cf\fR parameter settings.
This feature is available with Postfix 2.10 and later.
.IP \fB-p\fR
Show \fBmain.cf\fR parameter settings. This is the default.
.IP \fB-P\fR
Show \fBmaster.cf\fR service parameter settings (by default
all services and all parameters). formatted as one
"\fIservice/type/parameter=value\fR" per line. Specify
\fB-Pf\fR to fold long lines.
Specify one or more "\fIservice/type/parameter\fR" instances
on the \fBpostconf\fR(1) command line to limit the output
to parameters of interest. Trailing parameter name or
service type fields that are omitted will be handled as "*"
wildcard fields.
This feature is available with Postfix 2.11 and later.
.IP "\fB-t\fR [\fItemplate_file\fR]"
Display the templates for text that appears at the beginning
of delivery status notification (DSN) messages, without
@ -283,34 +365,59 @@ line (in shell language: "").
This feature is available with Postfix 2.3 and later.
.IP \fB-v\fR
Enable verbose logging for debugging purposes. Multiple \fB-v\fR
options make the software increasingly verbose.
Enable verbose logging for debugging purposes. Multiple
\fB-v\fR options make the software increasingly verbose.
.IP \fB-x\fR
Expand \fI$name\fR in \fBmain.cf\fR or \fBmaster.cf\fR
parameter values. The expansion is recursive.
This feature is available with Postfix 2.10 and later.
.IP \fB-X\fR
Edit the \fBmain.cf\fR configuration file, and remove
the parameters named on the \fBpostconf\fR(1) command line.
The file is copied to a temporary file then renamed into
place.
Edit the \fBmain.cf\fR configuration file, and remove the
parameters named on the \fBpostconf\fR(1) command line.
Specify a list of parameter names, not "\fIname=value\fR"
pairs. There is no \fBpostconf\fR(1) command to perform
the reverse operation.
pairs.
With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
and remove one or more service entries as specified with
"\fIservice/type\fR" on the \fBpostconf\fR(1) command line.
With \fB-P\fR, edit the \fBmaster.cf\fR configuration file,
and remove one or more service parameter settings (-o
parameter=value settings) as specied with
"\fIservice/type/parameter\fR" on the \fBpostconf\fR(1)
command line.
In all cases the file is copied to a temporary file then
renamed into place. Specify quotes to protect special
characters on the \fBpostconf\fR(1) command line.
There is no \fBpostconf\fR(1) command to perform the reverse
operation.
This feature is available with Postfix 2.10 and later.
Support for -M and -P was added with Postfix 2.11.
.IP \fB-#\fR
Edit the \fBmain.cf\fR configuration file, and comment out
the parameters named on the \fBpostconf\fR(1) command line,
so that those parameters revert to their default values.
The file is copied to a temporary file then renamed into
place.
Specify a list of parameter names, not "\fIname=value\fR"
pairs. There is no \fBpostconf\fR(1) command to perform
the reverse operation.
pairs.
This feature is available with Postfix 2.6 and later.
With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
and comment out one or more service entries as specified
with "\fIservice/type\fR" on the \fBpostconf\fR(1) command
line.
In all cases the file is copied to a temporary file then
renamed into place. Specify quotes to protect special
characters on the \fBpostconf\fR(1) command line.
There is no \fBpostconf\fR(1) command to perform the reverse
operation.
This feature is available with Postfix 2.6 and later. Support
for -M was added with Postfix 2.11.
.SH DIAGNOSTICS
.ad
.fi
@ -327,8 +434,8 @@ Directory with Postfix configuration files.
.nf
.ad
.fi
The following \fBmain.cf\fR parameters are especially relevant to
this program.
The following \fBmain.cf\fR parameters are especially
relevant to this program.
The text below provides only a parameter summary. See
\fBpostconf\fR(5) for more details including examples.
@ -341,20 +448,20 @@ Pathname of a configuration file with bounce message templates.
.na
.nf
/etc/postfix/main.cf, Postfix configuration parameters
/etc/postfix/master.cf, Postfix master daemon configuraton
/etc/postfix/master.cf, Postfix master daemon configuration
.SH "SEE ALSO"
.na
.nf
bounce(5), bounce template file format
master(5), master.cf configuration file syntax
postconf(5), main.cf configuration file syntax
bounce(5), bounce template file format master(5), master.cf
configuration file syntax postconf(5), main.cf configuration
file syntax
.SH "README FILES"
.na
.nf
.ad
.fi
Use "\fBpostconf readme_directory\fR" or
"\fBpostconf html_directory\fR" to locate this information.
Use "\fBpostconf readme_directory\fR" or "\fBpostconf
html_directory\fR" to locate this information.
.na
.nf
DATABASE_README, Postfix lookup table overview
@ -363,11 +470,10 @@ DATABASE_README, Postfix lookup table overview
.nf
.ad
.fi
The Secure Mailer license must be distributed with this software.
The Secure Mailer license must be distributed with this
software.
.SH "AUTHOR(S)"
.na
.nf
Wietse Venema
IBM T.J. Watson Research
P.O. Box 704
Yorktown Heights, NY 10598, USA
Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown
Heights, NY 10598, USA

View File

@ -38,8 +38,8 @@ can be stored under a fixed lookup key.
When a transaction fails due to a full database, Postfix
resizes the database and retries the transaction.
Postfix access, address mapping and routing tables will
generate partial search keys such as domain names without
Postfix access, address mapping and routing table lookups
may generate partial search keys such as domain names without
one or more subdomains, network addresses without one or
more least-significant octets, or email addresses without
the localpart, address extension or domain portion.
@ -47,7 +47,7 @@ This behavior is also found with btree:, hash:, or ldap:
tables.
Unlike other flat-file based Postfix databases, changes to
an LMDB database do not require automatic daemon program
an LMDB database do not trigger automatic daemon program
restart.
.SH "RELIABILITY"
.na
@ -63,10 +63,12 @@ curruption due stray pointer bugs.
The Postfix LMDB adapter implements locking with fcntl(2)
locks at whole-file granularity. LMDB's native locking
scheme would require world-writable lockfiles and would
therefore violate the Postfix security model. Unlike some
other Postfix flat-file databases, LMDB databases can safely
be updated without serializing requests through the proxymap(8)
service.
therefore violate the Postfix security model.
Multiple processes can safely update an LMDB database without
serializing requests through the proxymap(8) service. This
makes LMDB suitable as a shared cache for verify(8) or
postscreen(8) services.
.SH "CONFIGURATION PARAMETERS"
.na
.nf

View File

@ -12,10 +12,10 @@ Postfix configuration parameters
.SH DESCRIPTION
.ad
.fi
The Postfix main.cf configuration file specifies a small subset
of all the parameters that control the operation of the Postfix
mail system. Parameters not specified in main.cf are left at their
default values.
The Postfix main.cf configuration file specifies parameters that
control the operation of the Postfix mail system. Typically the
file contains only a small subset of all parameters; parameters
not specified are left at their default values.
.PP
The general format of the main.cf file is as follows:
.IP \(bu
@ -5131,23 +5131,27 @@ recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
.ft R
.SH recipient_delimiter (default: empty)
The set of characters that can separate a user name from its
address extension (user+foo). See \fBcanonical\fR(5), \fBlocal\fR(8), \fBrelocated\fR(5)
and \fBvirtual\fR(5) for the effects this has on aliases, canonical,
virtual, and relocated lookups. Basically, the software tries
user+foo and .forward+foo before trying user and .forward.
.PP
This implementation recognizes one delimiter character per email
address, and one address extension per email address.
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo). Basically, the software tries
user+foo and .forward+foo before trying user and .forward. This
implementation recognizes one delimiter character and one extension
per email address or .forward file name.
.PP
When the recipient_delimiter set contains multiple characters
(Postfix 2.11 and later), a user name is separated from its address
extension by the first character that matches the recipient_delimiter
set.
(Postfix 2.11 and later), a user name or .forward file name is
separated from its extension by the first character that matches
the recipient_delimiter set.
.PP
See \fBcanonical\fR(5), \fBlocal\fR(8), \fBrelocated\fR(5) and \fBvirtual\fR(5) for the
effects of recipient_delimiter on lookups in aliases, canonical,
virtual, and relocated maps, and see the propagate_unmatched_extensions
parameter for propagating an extension from one email address to
another.
.PP
When used in command_execution_directory, forward_path, or
luser_relay, ${recipient_delimiter} is replaced
with the recipient delimiter that was found in the recipient email
address (Postfix 2.11 and later), or it is replaced with the main.cf
luser_relay, ${recipient_delimiter} is replaced with the actual
recipient delimiter that was found in the recipient email address
(Postfix 2.11 and later), or it is replaced with the main.cf
recipient_delimiter parameter value (Postfix 2.10 and earlier).
.PP
The recipient_delimiter is not applied to the mailer-daemon
@ -7220,6 +7224,39 @@ whitespace, commas or colons. In the policy table "protocols" attribute
empty value means allow all protocols. The valid protocol names, (see
\\fBfBSSL_get_version\fR(3)\fR), are "SSLv2", "SSLv3" and "TLSv1".
.PP
With Postfix >= 2.5 the parameter syntax was expanded to support
protocol exclusions. One can explicitly exclude "SSLv2" by setting
"smtp_tls_mandatory_protocols = !SSLv2". To exclude both "SSLv2" and
"SSLv3" set "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the underlying OpenSSL interface semantics.
.PP
The range of protocols advertised by an SSL/TLS client must be
contiguous. When a protocol version is enabled, disabling any
higher version implicitly disables all versions above that higher
version. Thus, for example:
.sp
.in +4
.nf
.na
.ft C
smtp_tls_mandatory_protocols = !SSLv2, !TLSv1
.fi
.ad
.ft R
.in -4
also disables any protocols version higher than TLSv1 leaving
only "SSLv3" enabled.
.PP
Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". When Postfix <= 2.5 is linked against OpenSSL 1.0.1
or later, these, or any other new protocol versions, cannot be
disabled except by also disabling "TLSv1" (typically leaving just
"SSLv3"). The latest patch levels of Postfix >= 2.6, and all
versions of Postfix >= 2.10 can explicitly disable support for
"TLSv1.1" or "TLSv1.2".
.PP
At the dane and
dane-only security
levels, when usable TLSA records are obtained for the remote SMTP
@ -7227,23 +7264,10 @@ server, the Postfix SMTP client is obligated to include the SNI TLS
extension in its SSL client hello message. This may help the remote
SMTP server live up to its promise to provide a certificate that
matches its TLSA records. Since TLS extensions require TLS 1.0 or
later, the Postfix SMTP client must disable SSLv2 and SSLv3 when
later, the Postfix SMTP client must disable "SSLv2" and "SSLv3" when
SNI is required. If you use "dane" or "dane-only" do not disable
TLSv1, except perhaps via the policy table for destinations which
you are sure will support TLSv1.1 or TLSv1.2.
.PP
Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled.
.PP
With Postfix >= 2.5 the parameter syntax is expanded to support
protocol exclusions. One can now explicitly exclude SSLv2 by setting
"smtp_tls_mandatory_protocols = !SSLv2". To exclude both SSLv2 and
SSLv3 set "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the behavior when the OpenSSL library is newer than Postfix.
you are sure will support "TLSv1.1" or "TLSv1.2".
.PP
Since SSL version 2 has known protocol weaknesses and is now
deprecated, the default setting excludes "SSLv2". This means that by
@ -7258,9 +7282,9 @@ Example:
.nf
.na
.ft C
# Preferred form with Postfix >= 2.5:
# Preferred syntax with Postfix >= 2.5:
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
smtp_tls_mandatory_protocols = TLSv1
.fi
.ad
@ -7415,23 +7439,17 @@ Opportunistic DANE TLS. The TLS policy for the destination is
obtained via TLSA records in DNSSEC. If no TLSA records are found,
the effective security level used is may. If TLSA records are
found, but none are usable, the effective security level is encrypt. When usable
TLSA records are obtained for the remote SMTP server, SSLv2 and
SSLv3 are automatically disabled (see smtp_tls_mandatory_protocols),
and the server certificate must match the TLSA records. The
tls_dane_trust_anchor_digest_enable parameter controls optional
support for trust-anchor digest TLSA records. RFC 6698 (DANE) TLS
authentication and DNSSEC support is available with Postfix 2.11
and later.
TLSA records are obtained for the remote SMTP server, the
server certificate must match the TLSA records. RFC 6698 (DANE)
TLS authentication and DNSSEC support is available with Postfix
2.11 and later.
.br
.IP "\fBdane-only\fR"
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 connection is made to the server. When
usable TLSA records are obtained for the remote SMTP server, SSLv2
and SSLv3 are automatically disabled (see smtp_tls_mandatory_protocols),
and the server certificate must match the TLSA records. The
tls_dane_trust_anchor_digest_enable parameter controls optional
support for trust-anchor digest TLSA records. RFC 6698 (DANE) TLS
usable TLSA records are obtained for the remote SMTP server, the
server certificate must match the TLSA records. RFC 6698 (DANE) TLS
authentication and DNSSEC support is available with Postfix 2.11
and later.
.br
@ -7532,24 +7550,41 @@ separator is colon. An empty value means allow all protocols. The valid
protocol names, (see \\fBfBSSL_get_version\fR(3)\fR), are "SSLv2", "SSLv3"
and "TLSv1".
.PP
The range of protocols advertised by an SSL/TLS client must be
contiguous. When a protocol version is enabled, disabling any
higher version implicitly disables all versions above that higher
version. Thus, for example:
.sp
.in +4
.nf
.na
.ft C
smtp_tls_mandatory_protocols = !SSLv2, !TLSv1
.fi
.ad
.ft R
.in -4
also disables any protocols version higher than TLSv1 leaving
only "SSLv3" enabled.
.PP
Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled.
and "TLSv1.2". The latest patch levels of Postfix >= 2.6, and all
versions of Postfix >= 2.10 can explicitly disable support for
"TLSv1.1" or "TLSv1.2"
.PP
To include a protocol list its name, to exclude it, prefix the name
with a "!" character. To exclude SSLv2 even for opportunistic TLS set
"smtp_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set
"smtp_tls_protocols = !SSLv2, !SSLv3". Explicitly listing the protocols to
include, rather than protocols to exclude, is supported, but not
recommended. The exclusion form more closely matches the behavior
when the OpenSSL library is newer than Postfix.
recommended. The exclusion form more closely matches the underlying
OpenSSL interface semantics.
.PP
Example:
.nf
.na
.ft C
# TLSv1 only!
# TLSv1 or better:
smtp_tls_protocols = !SSLv2, !SSLv3
.fi
.ad
@ -7666,20 +7701,16 @@ parameter. When TLSA records are not found or are all unusable the
effective security level is "may" or "encrypt" respectively. For
purposes of protocol and cipher selection, the "dane" security level
is treated like a "mandatory" TLS security level, and weak ciphers
and protocols are disabled. SSLv2 and SSLv3 are automatically
disabled when usable TLSA records are obtained for the remote SMTP
server, see smtp_tls_mandatory_protocols for details. Since DANE
authenticates server certificates the "aNULL" cipher-suites are
transparently excluded at this level, no need to configure this
manually. The tls_dane_trust_anchor_digest_enable main.cf parameter
controls optional support for trust-anchor digest TLSA records.
RFC 6698 (DANE) TLS authentication is available with Postfix 2.11
and later.
and protocols are disabled. Since DANE authenticates server
certificates the "aNULL" cipher-suites are transparently excluded
at this level, no need to configure this manually. RFC 6698 (DANE)
TLS authentication is available with Postfix 2.11 and later.
.br
.IP "\fBdane-only\fR"
Mandatory DANE TLS. This is just like "dane" above, only DANE
TLSA authentication is mandatory. RFC 6698 (DANE) TLS authentication
is available with Postfix 2.11 and later.
Mandatory DANE TLS. This is just like "dane" above, but DANE
TLSA authentication is required. There is no fallback to "may" or
"encrypt" when TLSA records are missing or unusable. RFC 6698
(DANE) TLS authentication is available with Postfix 2.11 and later.
.br
.IP "\fBfingerprint\fR"
Certificate fingerprint verification.
@ -10599,24 +10630,26 @@ works in addition to the exclusions listed with smtpd_tls_exclude_ciphers
This feature is available in Postfix 2.3 and later.
.SH smtpd_tls_mandatory_protocols (default: !SSLv2)
The SSL/TLS protocols accepted by the Postfix SMTP server with
mandatory TLS encryption. If the list is empty, the server supports all
available SSL/TLS protocol versions. A non-empty value is a list
of protocol
names separated by whitespace, commas or colons. The supported protocol
names are "SSLv2", "SSLv3" and "TLSv1", and are not case sensitive.
mandatory TLS encryption. If the list is empty, the server supports
all available SSL/TLS protocol versions. A non-empty value is a
list of protocol names separated by whitespace, commas or colons.
The supported protocol names are "SSLv2", "SSLv3" and "TLSv1", and
are not case sensitive.
.PP
Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled.
.PP
With Postfix >= 2.5 the parameter syntax is expanded to support
protocol exclusions. One can now explicitly exclude SSLv2 by setting
"smtpd_tls_mandatory_protocols = !SSLv2". To exclude both SSLv2 and
SSLv3 set "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
With Postfix >= 2.5 the parameter syntax was expanded to support
protocol exclusions. One can explicitly exclude "SSLv2" by setting
"smtpd_tls_mandatory_protocols = !SSLv2". To exclude both "SSLv2" and
"SSLv3" set "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the behavior when the OpenSSL library is newer than Postfix.
matches the underlying OpenSSL interface semantics.
.PP
Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". When Postfix <= 2.5 is linked against OpenSSL 1.0.1
or later, these, or any other new protocol versions, cannot be
disabled. The latest patch levels of Postfix >= 2.6, and all
versions of Postfix >= 2.10 can disable support for "TLSv1.1" or
"TLSv1.2".
.PP
Since SSL version 2 has known protocol weaknesses and is now
deprecated, the default setting excludes "SSLv2". This means that
@ -10628,9 +10661,10 @@ Example:
.nf
.na
.ft C
smtpd_tls_mandatory_protocols = TLSv1
# Alternative form with Postfix >= 2.5:
# Preferred syntax with Postfix >= 2.5:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
.fi
.ad
.ft R
@ -10638,28 +10672,25 @@ smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
This feature is available in Postfix 2.3 and later.
.SH smtpd_tls_protocols (default: empty)
List of TLS protocols that the Postfix SMTP server will exclude
or include with opportunistic TLS encryption. This parameter SHOULD be
left at its default empty value, allowing all protocols to be used with
opportunistic TLS.
.PP
In main.cf the values are separated by whitespace, commas or
colons. An empty value means allow all protocols. The valid protocol
names, (see \\fBfBSSL_get_version\fR(3)\fR), are "SSLv2", "SSLv3" and
"TLSv1". In smtp_tls_policy_maps table entries, "protocols" attribute
values are separated by a colon.
or include with opportunistic TLS encryption. This parameter SHOULD
be left at its default empty value, allowing all protocols to be
used with opportunistic TLS. A non-empty value is a list of protocol
names separated by whitespace, commas or colons. The supported
protocol names are "SSLv2", "SSLv3" and "TLSv1", and are not case
sensitive.
.PP
Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled.
and "TLSv1.2". The latest patch levels of Postfix >= 2.6, and all
versions of Postfix >= 2.10 can disable support for "TLSv1.1" or
"TLSv1.2".
.PP
To include a protocol list its name, to exclude it, prefix the name
with a "!" character. To exclude SSLv2 even for opportunistic TLS set
"smtpd_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set
"smtpd_tls_protocols = !SSLv2, !SSLv3". Explicitly listing the protocols to
include, rather than protocols to exclude, is supported, but not
recommended. The exclusion form more closely matches the behavior
when the OpenSSL library is newer than Postfix.
recommended. The exclusion form more closely matches the underlying
OpenSSL interface semantics.
.PP
Example:
.nf
@ -11007,78 +11038,110 @@ bytes (equivalent to 256 bits) is sufficient to generate a 128bit
(or 168bit) session key.
.PP
This feature is available in Postfix 2.2 and later.
.SH tls_dane_digest_agility (default: on)
Configure DANE TLSA digest algorithm agility. When digest
algorithm agility is enabled, and the server and client support a
common strong digest algorithm, TLSA records with weaker digest
algorithms are ignored.
.PP
Specify one of the following:
.IP "\fBoff\fR"
DANE verification examines each well-formed record in the TLSA
RRset whose matching type is either "0" (no hash used) or is one of
the digest algorithms listed in $tls_dane_digests. This setting
is not recommended.
.br
.IP "\fBon\fR"
From each group of well-formed TLSA RRs a non-zero digest
matching type with the same certificate usage and selector, DANE
verification examines only those records whose matching type has
the highest precedence (appear earliest in $tls_dane_digests).
.br
.IP "\fBmaybe\fR"
For compatibility with digest algorithm agility, each certificate
or public key whose digest is included in a DANE TLSA RRset, SHOULD
be published with the same set of digest matching type values as
any other with the same usage and selector. Therefore, compatible
TLSA RRsets will contain an identical count of well-formed RRs with
each non-zero digest matching type for any fixed combination of
usage and selector. When this constraint is violated, or any of
the digest records are malformed, digest algorithm agility will
disabled. Otherwise, digest algorithm agility is enabled.
.br
.br
.PP
Digest algorithm agility ensures that the strongest digest
supported by both the Postfix SMTP client and the remote server is
used, and weaker digests are ignored. This supports non-disruptive
deprecation of outdated digest algorithms.
.PP
To ensure compatibility with digest algorithm agility during
key rotation, when a certificate or public key is being replaced
with another, and both are published during the transition, both
the old and the new certificate MUST be specified with the same set
of digests. One can change the list of digest algorithms later,
once old keys are retired. At any given time, change either the
list of digests without changing the list of certificates or public
keys or the list of certificates or public keys without changing
the list of digests. Full value matching type "0" records are not
subject to this constraint, but are discouraged due to the size of
the resulting DNS records.
.PP
It is expected that this algorithm agility mechanism will be
published in a standards track RFC for SMTP with DANE, and also in
an eventual update to RFC 6698.
.PP
This feature is available in Postfix 2.11 and later.
.SH tls_dane_digests (default: sha512 sha256)
RFC 6698 TLSA resource-record "matching type" digest algorithms
in descending preference order. All the specified algorithms must
be supported by the underlying OpenSSL library, otherwise the Postfix
SMTP client will not support DANE TLSA security.
.PP
Specify a list of digest names separated by commas and/or
whitespace. Each digest name may be followed by an optional
"=<number>" suffix. For example, "sha512" may instead be specified
as "sha512=2" and "sha256" may instead be specified as "sha256=1".
The optional number must match the <a
href="https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml#matching-types"
>IANA assigned TLSA matching type number the algorithm in question.
Postfix will check this constraint for the algorithms it knows about.
Additional matching type algorithms registered with IANA can be added
with explicit numbers provided they are supported by OpenSSL.
.PP
Invalid list elements are logged with a warning and disable DANE
support. TLSA RRs that specify digests not included in the list are
ignored with a warning.
.PP
Note: It is unwise to omit sha256 from the digest list. This
digest algorithm is the only mandatory to implement digest algorithm
in RFC 6698, and many servers are expected publish TLSA records
with just sha256 digests. Unless one of the standard digests is
seriously compromised and servers have had ample time to update their
TLSA records you should not omit any standard digests, just arrange
them in order from strongest to weakest.
.PP
When for a particular combination of "certificate usage" and
"selector" the TLSA RRset contains a well-formed record with a
matching type of "0", i.e. a full value of the associated certificate
or public key, the Postfix SMTP client will ignore all other matching
types for the same certificate usage and selector. In this case
the first algorithm listed in tls_dane_digests will be used to
compute a digest of the full value, which will then be used to match
certificates or public keys in the server's certificate chain.
"selector" the TLSA RRset contains records with more than one digest
matching type, the tls_dane_digest_agility parameter determines
whether all the RRs are used, or only those with the most preferred
digest matching type.
.PP
Otherwise, when for a particular combination of "certificate
usage" and "selector" the TLSA RRset contains a records with more
than one non-zero matching type, i.e. multiple digest algorithms,
only records with the highest preference digest are used after
discarding any records with an incorrect digest length as unusable.
The tls_dane_trust_anchor_digest_enable parameter controls
whether any digest TLSA records are acceptable in usage "2" (trust
anchor assertion) TLSA records.
.PP
This strategy ensures that the strongest digest supported by
both the Postfix SMTP client and the remote server is used, and
weaker digests are ignored. This supports non-disruptive deprecation
of outdated digest algorithms.
.PP
The strategy requires that when a TLSA RRset provides association
data for multiple certificates or public keys, all RRs with the same
"certificate usage" and "selector" be published with the same set
of digests. In particular, during key rotation, when a certificate
or public key is being replaced with another (and both are published
during the transition) both the old and the new certificate MUST be
specified with the same set of digests. One can change the list of
digest algorithms later, once old keys are retired. At any given
time change either the list of digests without changing the list of
certificates or public keys or the list of certificates or public
keys without changing the list of digests.
.PP
It is expected that this algorithm agility mechanism will be
published in a standards track RFC for SMTP with DANE, and perhaps
in an eventual update to RFC 6698.
.PP
This feature is available in Postfix 2.11.
.SH tls_dane_trust_anchor_digest_enable (default: trust-anchor-assertion)
This feature is available in Postfix 2.11 and later.
.SH tls_dane_trust_anchor_digest_enable (default: yes)
RFC 6698 trust-anchor digest support in the Postfix TLS library.
Specify zero or more of the following options, separated by comma or
whitespace. Option names are case-insensitive.
.IP "\fBca-constraint\fR"
Enable support for RFC 6698 (DANE TLSA) DNS records that
contain digests of trust-anchors with certificate usage "0".
These are often public root CAs, and server operators may
expect that clients will have the corresponding root certificate
in their CAfile or CApath. Most SSL/TLS servers do not send public
root CA certificate in their certificate chain, so if Postfix does
not have the CA certificate locally, there is no way to associate
the digest with the trust chain from the server. These TLSA records
are fragile, and only work when you have a complete (whatever that
means) set of public CAs in your CAfile or CApath. Enable this
with caution if at all.
.br
.IP "\fBtrust-anchor-assertion\fR"
Enable support for RFC 6698 (DANE TLSA) DNS records that contain
digests of trust-anchors with certificate usage "2". In this case
the certificate usage logically requires the server administrator
to configure the server to include the trust-anchor certificate in
the server's SSL certificate chain. These TLSA records are less
fragile than "ca-constraint" TLSA records, and are enabled by
default. Having a "complete" CAfile or CApath does not help in
this case, you are at the mercy of the remote server administrator's
competence.
.br
.br
the server's SSL certificate chain. If enough domains mess this
up, you can disable support for these TLSA records, but you'll no
longer have secure connections that get it right and only publish
trust anchor records.
.PP
At the dane
security level, when a TLSA RRset includes only unusable associations,
@ -11088,6 +11151,10 @@ security level. At the dane-only security level,
the server in question is skipped and delivery is deferred if no
secure servers are found.
.PP
The tls_dane_digests parameter controls the list of digest
algorithms that are supported in TLSA records. The tls_dane_digest_agility
parameter controls digest algorithm downgrade attack resistance.
.PP
This feature is available in Postfix 2.11 and later.
.SH tls_disable_workarounds (default: see "postconf -d" output)
List or bit-mask of OpenSSL bug work-arounds to disable.
@ -11301,7 +11368,11 @@ or performant cipher choice, there is some risk of interoperability
issues. In the past, some SSL clients have listed lower priority ciphers
that they did not implement correctly. If the server chooses a cipher
that the client prefers less, it may select a cipher whose client
implementation is flawed.
implementation is flawed. Most notably Windows 2003 Microsoft
Exchange servers have flawed implementations of DES-CBC3-SHA, which
OpenSSL considers stronger than RC4-SHA. Enabling server cipher-suite
selection may create interoperability issues with Windows 2003
Microsoft Exchange clients.
.PP
This feature is available in Postfix 2.8 and later, in combination
with OpenSSL 0.9.7 and later.

View File

@ -576,7 +576,8 @@ key to the lookup result.
The location of the Postfix top-level queue directory.
.IP "\fBrecipient_delimiter (empty)\fR"
The set of characters that can separate a user name from its
address extension (user+foo).
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo).
.IP "\fBrequire_home_directory (no)\fR"
Require that a \fBlocal\fR(8) recipient's home directory exists
before mail delivery is attempted.

View File

@ -417,7 +417,8 @@ The process name of a Postfix command or daemon process.
The location of the Postfix top-level queue directory.
.IP "\fBrecipient_delimiter (empty)\fR"
The set of characters that can separate a user name from its
address extension (user+foo).
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo).
.IP "\fBsyslog_facility (mail)\fR"
The syslog facility of Postfix logging.
.IP "\fBsyslog_name (see 'postconf -d' output)\fR"

View File

@ -479,7 +479,7 @@ and/or public keys.
.IP "\fBsmtp_tls_force_insecure_host_tlsa_lookup (no)\fR"
Lookup the associated DANE TLSA RRset even when a hostname is
not an alias and its address records lie in an unsigned zone.
.IP "\fBtls_dane_trust_anchor_digest_enable (trust-anchor-assertion)\fR"
.IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR"
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.

View File

@ -1009,7 +1009,8 @@ The process name of a Postfix command or daemon process.
The location of the Postfix top-level queue directory.
.IP "\fBrecipient_delimiter (empty)\fR"
The set of characters that can separate a user name from its
address extension (user+foo).
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo).
.IP "\fBsmtpd_banner ($myhostname ESMTP $mail_name)\fR"
The text that follows the 220 status code in the SMTP greeting
banner.

View File

@ -135,7 +135,8 @@ With locally submitted mail, append the string ".$mydomain" to
addresses that have no ".domain" information.
.IP "\fBrecipient_delimiter (empty)\fR"
The set of characters that can separate a user name from its
address extension (user+foo).
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo).
.IP "\fBswap_bangpath (yes)\fR"
Enable the rewriting of "site!user" into "user@site".
.PP

View File

@ -1112,7 +1112,7 @@ while (<>) {
s/\b(static):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
s/\b(tcp):/<a href="tcp_table.5.html">$1<\/a>:/g;
s/\b(texthash):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
s/\b(unix):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
#s/\b(unix):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
# Do nice links for smtp:host:port etc.

View File

@ -233,7 +233,7 @@ creates a "generic" database when none exists. </p>
generic: Makefile
@echo Creating $@
@rm -f $@.tmp
@printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` &gt; $@.tmp
@printf '%s\t%s+root=%s\n' root ${MTAADMIN} `uname -n` &gt; $@.tmp
@mv $@.tmp generic
%.cdb: %

View File

@ -226,9 +226,11 @@ size of the server TLS handshake. </p>
</pre>
</blockquote>
<li> <p> If you use RFC 6698 TLSA "2 0 1" or "2 1 1" records to
<li> <p> If you publish RFC 6698 TLSA "2 0 1" or "2 1 1" records to
specify root CA certificate digests, you must include the corresponding
root CA certificates in the "server.pem" certificate file. </p>
root CA certificates in the "server.pem" certificate file. See the
documentation of the tls_dane_trust_anchor_digest_enable main.cf
parameter. </p>
<blockquote>
<pre>
@ -236,29 +238,20 @@ root CA certificates in the "server.pem" certificate file. </p>
</pre>
</blockquote>
<p> Remote SMTP clients will
be able to use the TLSA record you publish (which only contains the
certificate digest) only if they have access to the corresponding
certificate. Failure to verify certificates per the server's
published TLSA records will typically cause the SMTP client to defer
mail delivery. The foregoing also applies to "2 0 2" and "2 1 2"
TLSA records or any other digest of a CA certificate, but it is
expected that SHA256 will be by far the most common digest for TLSA.
You are <i>strongly</i> urged to likewise include the root CA
certificate in your server certificate file even if you use "0 0
1" or "0 1 1" TLSA records. Some DANE implementations in SMTP
clients (Postfix among them) may treat RFC 6698 certificate usages
"0" and "2" interchangeably. </p>
<p> Remote SMTP clients will be able to use the TLSA record you
publish (which only contains the certificate digest) only if they
have access to the corresponding certificate. Failure to verify
certificates per the server's published TLSA records will typically
cause the SMTP client to defer mail delivery. The foregoing also
applies to "2 0 2" and "2 1 2" TLSA records or any other digest of
a CA certificate, but it is expected that SHA256 will be by far the
most common digest for TLSA. </p>
<p>By default, support for TLSA records that specify certificate
usage "0" via a digest is disabled in the Postfix SMTP client. As
a best practice, publish either "3 0 1" or "3 1 1" TLSA associations
that specify the SHA256 digest of the server certificate public key
with the alias-expanded hostname of each STARTTLS capable SMTP
server. These continue to work when a certificate is renewed with
the same public/private key pair. See the documentation of the
tls_dane_trust_anchor_digest_enable main.cf parameter for details.
</p>
<p> As a best practice, publish either "3 0 1" or "3 1 1" TLSA
associations that specify the SHA256 digest of the server certificate
public key with the alias-expanded hostname of each STARTTLS capable
SMTP server. These continue to work when a certificate is renewed
with the same public/private key pair. </p>
</ul>
@ -614,7 +607,7 @@ from scratch. </p>
<p> Since Postfix uses multiple smtpd(8) service processes, an
in-memory cache is not sufficient for session re-use. Clients store
at most one cached session per server and are very unlikey to
at most one cached session per server and are very unlikely to
repeatedly connect to the same server process. Thus session caching
in the Postfix SMTP server generally requires a shared cache (an
alternative available with Postfix &ge; 2.11 is described below).
@ -861,8 +854,8 @@ certificates</a> that use <b>only</b> the anonymous ciphers. This is
enabled by explicitly setting "smtpd_tls_cert_file = none"
and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. </p>
<p> Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade
ciphers: </p>
<p> Example, MSA that requires TLSv1 or higher, not SSLv2 or SSLv3,
with high grade ciphers: </p>
<blockquote>
<pre>
@ -872,9 +865,9 @@ ciphers: </p>
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5
smtpd_tls_security_level = encrypt
# Preferred form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
</pre>
</blockquote>
@ -918,23 +911,27 @@ secure for most situations. </p>
</blockquote>
<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
allows TLS servers to preempt the TLS client's cipher preference list.
allows TLS servers to preempt the TLS client's cipher-suite preference list.
This is possible only with SSLv3 and later, as in SSLv2 the client
chooses the cipher from a list supplied by the server. </p>
chooses the cipher-suite from a list supplied by the server. </p>
<p> By default, the OpenSSL server selects the client's most preferred
cipher that the server supports. With SSLv3 and later, the server
may choose its own most preferred cipher that is supported (offered)
cipher-suite that the server supports. With SSLv3 and later, the server
may choose its own most preferred cipher-suite that is supported (offered)
by the client. Setting "tls_preempt_cipherlist = yes" enables server
cipher preferences. The default OpenSSL behavior applies with
cipher-suite preferences. The default OpenSSL behavior applies with
"tls_preempt_cipherlist = no". </p>
<p> While server cipher selection may in some cases lead to a more secure
or performant cipher choice, there is some risk of interoperability
issues. In the past, some SSL clients have listed lower priority ciphers
that they did not implement correctly. If the server chooses a cipher
that the client prefers less, it may select a cipher whose client
implementation is flawed. </p>
<p> While server cipher-suite selection may in some cases lead to
a more secure or performant cipher-suite choice, there is some risk
of interoperability issues. In the past, some SSL clients have
listed lower priority ciphers that they did not implement correctly.
If the server chooses a cipher that the client prefers less, it may
select a cipher whose client implementation is flawed. Most notably
Windows 2003 Microsoft Exchange servers have flawed implementations
of DES-CBC3-SHA, which OpenSSL considers stronger than RC4-SHA.
Enabling server cipher-suite selection may create interoperability
issues with Windows 2003 Microsoft Exchange clients. </p>
<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
@ -1251,17 +1248,30 @@ the mandatory "dane-only" level. </p>
href="#client_tls_may">opportunistic</a> TLS that is resistant to
man in the middle and downgrade attacks when the destination domain
uses DNSSEC to publish DANE TLSA records for its MX hosts. If a
remote SMTP server has usable DANE TLSA records, these will be used
to authenticate the server. If TLSA records are published for a
given remote SMTP server (implying TLS support), but are not usable
due to unsupported parameters, the Postfix SMTP client will use <a
remote SMTP server has "usable" (see RFC 6698) DANE TLSA records,
the server connection will be authenticated. When DANE authentication
fails, there is no fallback to unauthenticated or plaintext delivery. </p>
<p> If TLSA records are published for a given remote SMTP server
(implying TLS support), but are all "unusable" due to unsupported
parameters or malformed data, the Postfix SMTP client will use <a
href="#client_tls_encrypt">mandatory</a> unauthenticated TLS.
Otherwise, the Postfix SMTP client behavior is the same as with <a
href="#client_tls_may">may</a>. </p>
Otherwise, when no TLSA records are published, the Postfix SMTP
client behavior is the same as with <a href="#client_tls_may">may</a>. </p>
<p> TLSA records must be published in DNSSEC validated DNS zones.
Any TLSA records in DNS zones not protected via DNSSEC are ignored.
The Postfix SMTP client will not look for TLSA records associated
with MX hosts whose "A" or "AAAA" records lie in an "insecure" DNS
zone. Such lookups have been observed to cause interoperability
issues with poorly implemented DNS servers, and are in any case not
expected to ever yield "secure" results, since that would require
a very unlikely DLV DNS trust anchor configured between the host
record and the associated "_25._tcp" child TLSA record. </p>
<p> The "dane-only" level is a form of <a
href="#client_tls_secure">secure-channel</a> TLS based on the DANE PKI.
If usable TLSA records are present these are used to authenticate the
If "usable" TLSA records are present these are used to authenticate the
remote SMTP server. Otherwise, or when server certificate verification
fails, delivery via the server in question tempfails. </p>
@ -1271,73 +1281,51 @@ to be in effect, the destination domain's containing DNS zone must
be signed and the Postfix SMTP client's operating system must be
configured to send its DNS queries to a recursive DNS nameserver
that is able to validate the signed records. Each MX host's DNS
zone should also be signed, and should publish DANE TLSA (RFC 6698)
zone needs to also be signed, and needs to publish DANE TLSA (RFC 6698)
records that specify how that MX host's TLS certificate is to be
verified. TLSA records do not preempt the normal SMTP MX host
verified. </p>
<p> TLSA records do not preempt the normal SMTP MX host
selection algorithm, if some MX hosts support TLSA and others do
not, TLS security will vary from delivery to delivery. It is up
to the domain owner to configure their MX hosts and their DNS
sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the smtp_dns_support_level main.cf
parameter. The tls_dane_trust_anchor_digest_enable main.cf parameter
controls optional support for trust-anchor digest TLSA records.
controls support for trust-anchor digest TLSA records. The
tls_dane_digests and tls_dane_digest_agility parameters control
the list of supported digests and digest downgrade attack resistance.
</p>
<p> The Postfix SMTP client deviates from RFC 6698 in cases where
strict adherence is likely to create opportunities for delayed (or
eventually bounced) email with no substantive security gain. Most
notably, it is not expected that smtp_tls_CAfile and smtp_tls_CApath
can reasonably include every public CA that a remote SMTP server's
administrator may believe to be well-known. Therefore, certificate
usages "0" and "2" from RFC 6698 which are intended to "constrain"
existing PKI trust, are instead treated as "trust assertions" and
mapped to "1" and "3" respectively. That is, with certificate usage
"0" and "2", Postfix will not require the remote SMTP server's
certificate to be trusted with respect to any locally defined public
CAs, it is the domain owner's responsibility to ensure that the
certificate associations in their TLSA records are appropriate
to authenticate their SMTP servers. </p>
<p> DANE for SMTP MTAs deviates in some details from the baseline
DANE protocol in RFC 6698. Most notably, it is not expected that
SMTP MTAs can reasonably include every public CA that a remote SMTP
server's administrator may believe to be well-known. Nor is there
an interactive user to "click OK" when authentication fails. </p>
<p> In addition, the Postfix SMTP client does not assume that the
remote SMTP server will necessarily be configured to present the
certificate of any usage "0" root CA in its TLS protocol <a
href="https://tools.ietf.org/html/rfc2246#section-7.4.2">certificate_list</a>.
Therefore, support for usage "0" certificate and public-key digests
is disabled by default, see tls_dane_trust_anchor_digest_enable for
details. While undigested trust-anchor certificates in TLSA records
are supported, publishing complete certificates in DNS is unwise
given the resulting excessively large DNS record sizes. Therefore,
in its default configuration the Postfix SMTP client essentially
supports only certificate usages "1", "2" and "3" (with "1" treated as
though it were "3"). </p>
<p> Therefore, certificate usages "0" and "1" from RFC 6698 which
are intended to "constrain" existing PKI trust, are not supported.
TLSA records with usage "0" are treated as "unusable". TLSA records
with usage "1" are instead treated as "trust assertions" and mapped
to usage "3". Specifically, with certificate usage "1", Postfix
will not require the remote SMTP server's certificate to be trusted
with respect to any locally defined public CAs, it is the domain
owner's responsibility to ensure that the certificate associations
in their TLSA records are appropriate to authenticate their SMTP
servers. </p>
<p> Finally, the interaction of DANE with MX hostnames that are
CNAMEs differs from the draft specification in the names used to
construct the associated <a
href="https://tools.ietf.org/html/draft-ietf-dane-srv-02#section-3.2">TLSA
queries</a>. When the MX hostname is a CNAME, the draft proposal
to use the unexpanded MX hostname in TLSA lookups is fragile and
unintuitive. For this to work, the domain owner has to either
duplicate the TLSA records of the target (host, service) pair in
his own DNS or furnish the target host with an additional
certificate and private key that would be negotiated via SNI.
Neither of these are robust or easy to manage. It is far better
to expand the CNAME recursively to the underlying target hostname
(keeping track of DNSSEC validation along the way) and to use the
expanded name to construct the TLSA query and, if appropriate, in
server certificate name checks. This is the approach taken by the
Postfix SMTP client, and if sanity prevails will also be the approach
taken in the final standard. </p>
<p> The Postfix SMTP client supports only certificate usages "2"
and "3" (with "1" treated as though it were "3"). See
tls_dane_trust_anchor_digest_enable for usage "2" usability
considerations. Support for certificate usage "1" is an experiment,
it may be withdrawn in the future. Server operators SHOULD NOT
publish TLSA records with usage "1". </p>
<p> When usable TLSA records are obtained for the remote SMTP server
the Postfix SMTP client is obligated to include the SNI TLS extension
in its SSL client hello message. This may help the remote SMTP
server live up to its promise to provide a certificate that matches
its TLSA records. Since TLS extensions require TLS 1.0 or later,
the Postfix SMTP client must disable SSLv2 and SSLv3 when SNI is
required. If you use "dane" or "dane-only", do not disable TLSv1,
except perhaps via the policy table for destinations which you are
sure will support TLSv1.1 or TLSv1.2. </p>
the Postfix SMTP client sends the SNI TLS extension in its SSL
client hello message. This may help the remote SMTP server live
up to its promise to provide a certificate that matches its TLSA
records. </p>
<p> For purposes of protocol and cipher selection, the "dane"
security level is treated like a "mandatory" TLS security level,
@ -1357,14 +1345,14 @@ certificate must contain at least one of these names. </p>
<p> When a DANE TLSA record specifies an end-entity (EE) certificate,
(that is the actual server certificate), as with the fingerprint
security level below, no name checks or certificate expiration checks
are applied. The server certificate (or its public key) either matches
are applied. The server certificate (or its public key) either matches
the DANE record or not. Server administrators should publish such
EE records in preference to all other types. </p>
<p> The pre-requisites for DANE support in the Postfix SMTP client are: </p>
<ul>
<li> A <i>compile-time</i> OpenSSL library that supports the TLS SNI
extension and the "sha256" and "sha512" message digests.
extension and "SHA-2" message digests.
<li> A <i>compile-time</i> DNS resolver library that supports DNSSEC.
Postfix binaries built on an older system will not support DNSSEC even
if deployed on a system with an updated resolver library.
@ -2068,12 +2056,13 @@ server has a greater opportunity to mandate client security policy when
it is a dedicated MSA that only handles outbound mail from trusted clients,
below we focus on the client security policy. </p>
<p> On the SMTP client, there are further complications. When delivering
mail to a given domain, in contrast to HTTPS, one rarely uses the domain
name directly as the target host of the SMTP session. More typically,
one uses MX lookups - these are usually unauthenticated - to obtain the domain's SMTP server
hostname(s). When, as is current practice, the client verifies the
insecurely obtained MX hostname, it is subject to a DNS man-in-the-middle
<p> On the SMTP client, there are further complications. When
delivering mail to a given domain, in contrast to HTTPS, one rarely
uses the domain name directly as the target host of the SMTP session.
More typically, one uses MX lookups &mdash; these are usually
unauthenticated &mdash; to obtain the domain's SMTP server hostname(s).
When, as is current practice, the client verifies the insecurely
obtained MX hostname, it is subject to a DNS man-in-the-middle
attack. </p>
<p> Adoption of DNSSEC and RFC6698 (DANE) may gradually (as domains
@ -2184,24 +2173,19 @@ DNSSEC. If no TLSA records are found, the effective security level
used is <a href="#client_tls_may">may</a>. If TLSA records are
found, but none are usable, the effective security level is <a
href="#client_tls_encrypt">encrypt</a>. When usable TLSA records
are obtained for the remote SMTP server, SSLv2 and SSLv3 are
automatically disabled (see smtp_tls_mandatory_protocols), and the
server certificate must match the TLSA records. The
tls_dane_trust_anchor_digest_enable parameter controls optional
support for trust-anchor digest TLSA records. RFC 6698 (DANE) TLS
authentication and DNSSEC support is available with Postfix 2.11
and later. </dd>
are 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. </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
DNSSEC. If no TLSA records are found, or none are usable, no
connection is made to the server. When usable TLSA records are
obtained for the remote SMTP server, SSLv2 and SSLv3 are automatically
disabled (see smtp_tls_mandatory_protocols), and the server certificate
must match the TLSA records. The tls_dane_trust_anchor_digest_enable
parameter controls optional support for trust-anchor digest TLSA
records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
available with Postfix 2.11 and later. </dd>
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. </dd>
<dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
fingerprint verification.</a> Available with Postfix 2.5 and
@ -2291,9 +2275,8 @@ Example:
/etc/postfix/tls_policy:
example.edu none
example.mil may
example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high
example.com verify
match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high
example.gov encrypt ciphers=high
example.com verify match=hostname:dot-nexthop ciphers=high
example.net secure
.example.net secure match=.example.net:example.net
[mail.example.org]:587 secure match=nexthop
@ -2407,7 +2390,7 @@ the SSL/TLS protocols used with opportunistic TLS. </p>
smtp_tls_exclude_ciphers = aNULL
# Preferred form with Postfix &ge; 2.5:
smtp_tls_mandatory_protocols = !SSLv2
# Alternative form.
# Legacy form for Postifx &lt; 2.5:
smtp_tls_mandatory_protocols = SSLv3, TLSv1
# Also available with Postfix &ge; 2.6:
smtp_tls_ciphers = export

View File

@ -30,8 +30,8 @@
# When a transaction fails due to a full database, Postfix
# resizes the database and retries the transaction.
#
# Postfix access, address mapping and routing tables will
# generate partial search keys such as domain names without
# Postfix access, address mapping and routing table lookups
# may generate partial search keys such as domain names without
# one or more subdomains, network addresses without one or
# more least-significant octets, or email addresses without
# the localpart, address extension or domain portion.
@ -39,7 +39,7 @@
# tables.
#
# Unlike other flat-file based Postfix databases, changes to
# an LMDB database do not require automatic daemon program
# an LMDB database do not trigger automatic daemon program
# restart.
# RELIABILITY
# .ad
@ -53,10 +53,12 @@
# The Postfix LMDB adapter implements locking with fcntl(2)
# locks at whole-file granularity. LMDB's native locking
# scheme would require world-writable lockfiles and would
# therefore violate the Postfix security model. Unlike some
# other Postfix flat-file databases, LMDB databases can safely
# be updated without serializing requests through the proxymap(8)
# service.
# therefore violate the Postfix security model.
#
# Multiple processes can safely update an LMDB database without
# serializing requests through the proxymap(8) service. This
# makes LMDB suitable as a shared cache for verify(8) or
# postscreen(8) services.
# CONFIGURATION PARAMETERS
# .ad
# .fi

View File

@ -12,10 +12,10 @@ Postfix configuration parameters
.SH DESCRIPTION
.ad
.fi
The Postfix main.cf configuration file specifies a small subset
of all the parameters that control the operation of the Postfix
mail system. Parameters not specified in main.cf are left at their
default values.
The Postfix main.cf configuration file specifies parameters that
control the operation of the Postfix mail system. Typically the
file contains only a small subset of all parameters; parameters
not specified are left at their default values.
.PP
The general format of the main.cf file is as follows:
.IP \(bu

View File

@ -3505,23 +3505,27 @@ recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
%PARAM recipient_delimiter
<p> The set of characters that can separate a user name from its
address extension (user+foo). See canonical(5), local(8), relocated(5)
and virtual(5) for the effects this has on aliases, canonical,
virtual, and relocated lookups. Basically, the software tries
user+foo and .forward+foo before trying user and .forward. </p>
<p> This implementation recognizes one delimiter character per email
address, and one address extension per email address. </p>
extension (example: user+foo), or a .forward file name from its
extension (example: .forward+foo). Basically, the software tries
user+foo and .forward+foo before trying user and .forward. This
implementation recognizes one delimiter character and one extension
per email address or .forward file name. </p>
<p> When the recipient_delimiter set contains multiple characters
(Postfix 2.11 and later), a user name is separated from its address
extension by the first character that matches the recipient_delimiter
set. </p>
(Postfix 2.11 and later), a user name or .forward file name is
separated from its extension by the first character that matches
the recipient_delimiter set. </p>
<p> See canonical(5), local(8), relocated(5) and virtual(5) for the
effects of recipient_delimiter on lookups in aliases, canonical,
virtual, and relocated maps, and see the propagate_unmatched_extensions
parameter for propagating an extension from one email address to
another. </p>
<p> When used in command_execution_directory, forward_path, or
luser_relay, ${recipient_delimiter} is replaced
with the recipient delimiter that was found in the recipient email
address (Postfix 2.11 and later), or it is replaced with the main.cf
luser_relay, ${recipient_delimiter} is replaced with the actual
recipient delimiter that was found in the recipient email address
(Postfix 2.11 and later), or it is replaced with the main.cf
recipient_delimiter parameter value (Postfix 2.10 and earlier).
</p>
@ -10668,23 +10672,17 @@ the effective security level used is <a
href="TLS_README.html#client_tls_may">may</a>. If TLSA records are
found, but none are usable, the effective security level is <a
href="TLS_README.html#client_tls_encrypt">encrypt</a>. When usable
TLSA records are obtained for the remote SMTP server, SSLv2 and
SSLv3 are automatically disabled (see smtp_tls_mandatory_protocols),
and the server certificate must match the TLSA records. The
tls_dane_trust_anchor_digest_enable parameter controls optional
support for trust-anchor digest TLSA records. RFC 6698 (DANE) TLS
authentication and DNSSEC support is available with Postfix 2.11
and later. </dd>
TLSA records are obtained for the remote SMTP server, the
server certificate must match the TLSA records. RFC 6698 (DANE)
TLS authentication and DNSSEC support is available with Postfix
2.11 and later. </dd>
<dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt>
<dd>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 connection is made to the server. When
usable TLSA records are obtained for the remote SMTP server, SSLv2
and SSLv3 are automatically disabled (see smtp_tls_mandatory_protocols),
and the server certificate must match the TLSA records. The
tls_dane_trust_anchor_digest_enable parameter controls optional
support for trust-anchor digest TLSA records. RFC 6698 (DANE) TLS
usable TLSA records are obtained for the remote SMTP server, the
server certificate must match the TLSA records. RFC 6698 (DANE) TLS
authentication and DNSSEC support is available with Postfix 2.11
and later. </dd>
@ -10777,6 +10775,35 @@ whitespace, commas or colons. In the policy table "protocols" attribute
empty value means allow all protocols. The valid protocol names, (see
<b>SSL_get_version(3)</b>), are "SSLv2", "SSLv3" and "TLSv1". </p>
<p> With Postfix &ge; 2.5 the parameter syntax was expanded to support
protocol exclusions. One can explicitly exclude "SSLv2" by setting
"smtp_tls_mandatory_protocols = !SSLv2". To exclude both "SSLv2" and
"SSLv3" set "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the underlying OpenSSL interface semantics.
</p>
<p> The range of protocols advertised by an SSL/TLS client must be
contiguous. When a protocol version is enabled, disabling any
higher version implicitly disables all versions above that higher
version. Thus, for example: </p>
<blockquote>
<pre>
smtp_tls_mandatory_protocols = !SSLv2, !TLSv1
</pre>
</blockquote>
<p> also disables any protocols version higher than TLSv1 leaving
only "SSLv3" enabled. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". When Postfix &le; 2.5 is linked against OpenSSL 1.0.1
or later, these, or any other new protocol versions, cannot be
disabled except by also disabling "TLSv1" (typically leaving just
"SSLv3"). The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can explicitly disable support for
"TLSv1.1" or "TLSv1.2". </p>
<p> At the <a href="TLS_README.html#client_tls_dane">dane</a> and
<a href="TLS_README.html#client_tls_dane">dane-only</a> security
levels, when usable TLSA records are obtained for the remote SMTP
@ -10784,24 +10811,10 @@ server, the Postfix SMTP client is obligated to include the SNI TLS
extension in its SSL client hello message. This may help the remote
SMTP server live up to its promise to provide a certificate that
matches its TLSA records. Since TLS extensions require TLS 1.0 or
later, the Postfix SMTP client must disable SSLv2 and SSLv3 when
later, the Postfix SMTP client must disable "SSLv2" and "SSLv3" when
SNI is required. If you use "dane" or "dane-only" do not disable
TLSv1, except perhaps via the policy table for destinations which
you are sure will support TLSv1.1 or TLSv1.2. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
<p> With Postfix &ge; 2.5 the parameter syntax is expanded to support
protocol exclusions. One can now explicitly exclude SSLv2 by setting
"smtp_tls_mandatory_protocols = !SSLv2". To exclude both SSLv2 and
SSLv3 set "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the behavior when the OpenSSL library is newer than Postfix.
</p>
you are sure will support "TLSv1.1" or "TLSv1.2". </p>
<p> Since SSL version 2 has known protocol weaknesses and is now
deprecated, the default setting excludes "SSLv2". This means that by
@ -10814,9 +10827,9 @@ TLS_README for more information about security levels. </p>
<p> Example: </p>
<pre>
# Preferred form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
# Alternative form.
# Legacy syntax:
smtp_tls_mandatory_protocols = TLSv1
</pre>
@ -10970,25 +10983,26 @@ configuration parameter. See there for details. </p>
%PARAM smtpd_tls_mandatory_protocols !SSLv2
<p> The SSL/TLS protocols accepted by the Postfix SMTP server with
mandatory TLS encryption. If the list is empty, the server supports all
available SSL/TLS protocol versions. A non-empty value is a list
of protocol
names separated by whitespace, commas or colons. The supported protocol
names are "SSLv2", "SSLv3" and "TLSv1", and are not case sensitive. </p>
mandatory TLS encryption. If the list is empty, the server supports
all available SSL/TLS protocol versions. A non-empty value is a
list of protocol names separated by whitespace, commas or colons.
The supported protocol names are "SSLv2", "SSLv3" and "TLSv1", and
are not case sensitive. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
<p> With Postfix &ge; 2.5 the parameter syntax is expanded to support
protocol exclusions. One can now explicitly exclude SSLv2 by setting
"smtpd_tls_mandatory_protocols = !SSLv2". To exclude both SSLv2 and
SSLv3 set "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
<p> With Postfix &ge; 2.5 the parameter syntax was expanded to support
protocol exclusions. One can explicitly exclude "SSLv2" by setting
"smtpd_tls_mandatory_protocols = !SSLv2". To exclude both "SSLv2" and
"SSLv3" set "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing
the protocols to include, rather than protocols to exclude, is
supported, but not recommended. The exclusion form more closely
matches the behavior when the OpenSSL library is newer than Postfix.
</p>
matches the underlying OpenSSL interface semantics. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". When Postfix &le; 2.5 is linked against OpenSSL 1.0.1
or later, these, or any other new protocol versions, cannot be
disabled. The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can disable support for "TLSv1.1" or
"TLSv1.2". </p>
<p> Since SSL version 2 has known protocol weaknesses and is now
deprecated, the default setting excludes "SSLv2". This means that
@ -10998,9 +11012,10 @@ level. </p>
<p> Example: </p>
<pre>
smtpd_tls_mandatory_protocols = TLSv1
# Alternative form with Postfix &ge; 2.5:
# Preferred syntax with Postfix &ge; 2.5:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
</pre>
<p> This feature is available in Postfix 2.3 and later. </p>
@ -11063,21 +11078,18 @@ parameter. When TLSA records are not found or are all unusable the
effective security level is "may" or "encrypt" respectively. For
purposes of protocol and cipher selection, the "dane" security level
is treated like a "mandatory" TLS security level, and weak ciphers
and protocols are disabled. SSLv2 and SSLv3 are automatically
disabled when usable TLSA records are obtained for the remote SMTP
server, see smtp_tls_mandatory_protocols for details. Since DANE
authenticates server certificates the "aNULL" cipher-suites are
transparently excluded at this level, no need to configure this
manually. The tls_dane_trust_anchor_digest_enable main.cf parameter
controls optional support for trust-anchor digest TLSA records.
RFC 6698 (DANE) TLS authentication is available with Postfix 2.11
and later. </dd>
and protocols are disabled. Since DANE authenticates server
certificates the "aNULL" cipher-suites are transparently excluded
at this level, no need to configure this manually. RFC 6698 (DANE)
TLS authentication is available with Postfix 2.11 and later. </dd>
<dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt>
<dd>Mandatory DANE TLS. This is just like "dane" above, only DANE
TLSA authentication is mandatory. RFC 6698 (DANE) TLS authentication
is available with Postfix 2.11 and later. </dd>
<dd>Mandatory DANE TLS. This is just like "dane" above, but DANE
TLSA authentication is required. There is no fallback to "may" or
"encrypt" when TLSA records are missing or unusable. RFC 6698
(DANE) TLS authentication is available with Postfix 2.11 and later.
</dd>
<dt><b><a href="TLS_README.html#client_tls_fingerprint">fingerprint</a></b></dt>
<dd>Certificate fingerprint verification.
@ -12127,22 +12139,34 @@ separator is colon. An empty value means allow all protocols. The valid
protocol names, (see <b>SSL_get_version(3)</b>), are "SSLv2", "SSLv3"
and "TLSv1". </p>
<p> The range of protocols advertised by an SSL/TLS client must be
contiguous. When a protocol version is enabled, disabling any
higher version implicitly disables all versions above that higher
version. Thus, for example: </p>
<blockquote>
<pre>
smtp_tls_mandatory_protocols = !SSLv2, !TLSv1
</pre>
</blockquote>
<p> also disables any protocols version higher than TLSv1 leaving
only "SSLv3" enabled. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
and "TLSv1.2". The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can explicitly disable support for
"TLSv1.1" or "TLSv1.2"</p>
<p> To include a protocol list its name, to exclude it, prefix the name
with a "!" character. To exclude SSLv2 even for opportunistic TLS set
"smtp_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set
"smtp_tls_protocols = !SSLv2, !SSLv3". Explicitly listing the protocols to
include, rather than protocols to exclude, is supported, but not
recommended. The exclusion form more closely matches the behavior
when the OpenSSL library is newer than Postfix. </p>
recommended. The exclusion form more closely matches the underlying
OpenSSL interface semantics. </p>
<p> Example: </p>
<pre>
# TLSv1 only!
# TLSv1 or better:
smtp_tls_protocols = !SSLv2, !SSLv3
</pre>
@ -12151,28 +12175,25 @@ smtp_tls_protocols = !SSLv2, !SSLv3
%PARAM smtpd_tls_protocols
<p> List of TLS protocols that the Postfix SMTP server will exclude
or include with opportunistic TLS encryption. This parameter SHOULD be
left at its default empty value, allowing all protocols to be used with
opportunistic TLS. </p>
<p> In main.cf the values are separated by whitespace, commas or
colons. An empty value means allow all protocols. The valid protocol
names, (see <b>SSL_get_version(3)</b>), are "SSLv2", "SSLv3" and
"TLSv1". In smtp_tls_policy_maps table entries, "protocols" attribute
values are separated by a colon. </p>
or include with opportunistic TLS encryption. This parameter SHOULD
be left at its default empty value, allowing all protocols to be
used with opportunistic TLS. A non-empty value is a list of protocol
names separated by whitespace, commas or colons. The supported
protocol names are "SSLv2", "SSLv3" and "TLSv1", and are not case
sensitive. </p>
<p> Note: As of OpenSSL 1.0.1 two new protocols are defined, "TLSv1.1"
and "TLSv1.2". If an older Postfix version is linked against OpenSSL
1.0.1 or later, these, or any other new protocol versions, are
unconditionally enabled. </p>
and "TLSv1.2". The latest patch levels of Postfix &ge; 2.6, and all
versions of Postfix &ge; 2.10 can disable support for "TLSv1.1" or
"TLSv1.2". </p>
<p> To include a protocol list its name, to exclude it, prefix the name
with a "!" character. To exclude SSLv2 even for opportunistic TLS set
"smtpd_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set
"smtpd_tls_protocols = !SSLv2, !SSLv3". Explicitly listing the protocols to
include, rather than protocols to exclude, is supported, but not
recommended. The exclusion form more closely matches the behavior
when the OpenSSL library is newer than Postfix. </p>
recommended. The exclusion form more closely matches the underlying
OpenSSL interface semantics. </p>
<p> Example: </p>
<pre>
@ -14265,7 +14286,11 @@ or performant cipher choice, there is some risk of interoperability
issues. In the past, some SSL clients have listed lower priority ciphers
that they did not implement correctly. If the server chooses a cipher
that the client prefers less, it may select a cipher whose client
implementation is flawed. </p>
implementation is flawed. Most notably Windows 2003 Microsoft
Exchange servers have flawed implementations of DES-CBC3-SHA, which
OpenSSL considers stronger than RC4-SHA. Enabling server cipher-suite
selection may create interoperability issues with Windows 2003
Microsoft Exchange clients. </p>
<p> This feature is available in Postfix 2.8 and later, in combination
with OpenSSL 0.9.7 and later. </p>
@ -15256,41 +15281,17 @@ configuration parameter. See there for details. </p>
<p> This feature is available in Postfix 2.11 and later. </p>
%PARAM tls_dane_trust_anchor_digest_enable trust-anchor-assertion
%PARAM tls_dane_trust_anchor_digest_enable yes
<p> RFC 6698 trust-anchor digest support in the Postfix TLS library.
Specify zero or more of the following options, separated by comma or
whitespace. Option names are case-insensitive. </p>
<dl>
<dt><b>ca-constraint</b></dt>
<dd> Enable support for RFC 6698 (DANE TLSA) DNS records that
contain digests of trust-anchors with certificate usage "0".
These are often public root CAs, and server operators may
expect that clients will have the corresponding root certificate
in their CAfile or CApath. Most SSL/TLS servers do not send public
root CA certificate in their certificate chain, so if Postfix does
not have the CA certificate locally, there is no way to associate
the digest with the trust chain from the server. These TLSA records
are fragile, and only work when you have a complete (whatever that
means) set of public CAs in your CAfile or CApath. Enable this
with caution if at all. </dd>
<dt><b>trust-anchor-assertion</b></dt>
<dd> Enable support for RFC 6698 (DANE TLSA) DNS records that contain
Enable support for RFC 6698 (DANE TLSA) DNS records that contain
digests of trust-anchors with certificate usage "2". In this case
the certificate usage logically requires the server administrator
to configure the server to include the trust-anchor certificate in
the server's SSL certificate chain. These TLSA records are less
fragile than "ca-constraint" TLSA records, and are enabled by
default. Having a "complete" CAfile or CApath does not help in
this case, you are at the mercy of the remote server administrator's
competence. </dd>
</dl>
the server's SSL certificate chain. If enough domains mess this
up, you can disable support for these TLSA records, but you'll no
longer have secure connections that get it right and only publish
trust anchor records. </p>
<p> At the <a href="TLS_README.html#client_tls_dane">dane</a>
security level, when a TLSA RRset includes only unusable associations,
@ -15301,6 +15302,11 @@ href="TLS_README.html#client_tls_dane">dane-only</a> security level,
the server in question is skipped and delivery is deferred if no
secure servers are found. </p>
<p> The tls_dane_digests parameter controls the list of digest
algorithms that are supported in TLSA records. The tls_dane_digest_agility
parameter controls digest algorithm downgrade attack resistance.
</p>
<p> This feature is available in Postfix 2.11 and later. </p>
%PARAM tls_wildcard_matches_multiple_labels yes
@ -15448,47 +15454,104 @@ are not prepared to handle the new TLSA RRset. </p>
<p> This feature is available in Postfix 2.11. </p>
%PARAM tls_dane_digest_agility on
<p> Configure DANE TLSA digest algorithm agility. When digest
algorithm agility is enabled, and the server and client support a
common strong digest algorithm, TLSA records with weaker digest
algorithms are ignored. </p>
<p> Specify one of the following: </p>
<dl>
<dt><b>off</b></dt>
<dd> DANE verification examines each well-formed record in the TLSA
RRset whose matching type is either "0" (no hash used) or is one of
the digest algorithms listed in $tls_dane_digests. This setting
is not recommended. </dd>
<dt><b>on</b></dt>
<dd> From each group of well-formed TLSA RRs a non-zero digest
matching type with the same certificate usage and selector, DANE
verification examines only those records whose matching type has
the highest precedence (appear earliest in $tls_dane_digests).
</dd>
<dt><b>maybe</b></dt>
<dd> For compatibility with digest algorithm agility, each certificate
or public key whose digest is included in a DANE TLSA RRset, SHOULD
be published with the same set of digest matching type values as
any other with the same usage and selector. Therefore, compatible
TLSA RRsets will contain an identical count of well-formed RRs with
each non-zero digest matching type for any fixed combination of
usage and selector. When this constraint is violated, or any of
the digest records are malformed, digest algorithm agility will
disabled. Otherwise, digest algorithm agility is enabled. </dd>
</dl>
<p> Digest algorithm agility ensures that the strongest digest
supported by both the Postfix SMTP client and the remote server is
used, and weaker digests are ignored. This supports non-disruptive
deprecation of outdated digest algorithms. </p>
<p> To ensure compatibility with digest algorithm agility during
key rotation, when a certificate or public key is being replaced
with another, and both are published during the transition, both
the old and the new certificate MUST be specified with the same set
of digests. One can change the list of digest algorithms later,
once old keys are retired. At any given time, change either the
list of digests without changing the list of certificates or public
keys or the list of certificates or public keys without changing
the list of digests. Full value matching type "0" records are not
subject to this constraint, but are discouraged due to the size of
the resulting DNS records. </p>
<p> It is expected that this algorithm agility mechanism will be
published in a standards track RFC for SMTP with DANE, and also in
an eventual update to RFC 6698. </p>
<p> This feature is available in Postfix 2.11 and later. </p>
%PARAM tls_dane_digests sha512 sha256
<p> RFC 6698 TLSA resource-record "matching type" digest algorithms
in descending preference order. All the specified algorithms must
be supported by the underlying OpenSSL library, otherwise the Postfix
SMTP client will not support DANE TLSA security. </p>
SMTP client will not support DANE TLSA security. </p>
<p> Specify a list of digest names separated by commas and/or
whitespace. Each digest name may be followed by an optional
"=&lt;number&gt;" suffix. For example, "sha512" may instead be specified
as "sha512=2" and "sha256" may instead be specified as "sha256=1".
The optional number must match the <a
href="https://www.iana.org/assignments/dane-parameters/dane-parameters.xhtml#matching-types"
>IANA</a> assigned TLSA matching type number the algorithm in question.
Postfix will check this constraint for the algorithms it knows about.
Additional matching type algorithms registered with IANA can be added
with explicit numbers provided they are supported by OpenSSL. </p>
<p> Invalid list elements are logged with a warning and disable DANE
support. TLSA RRs that specify digests not included in the list are
ignored with a warning. </p>
<p> Note: It is unwise to omit sha256 from the digest list. This
digest algorithm is the only mandatory to implement digest algorithm
in RFC 6698, and many servers are expected publish TLSA records
with just sha256 digests. Unless one of the standard digests is
seriously compromised and servers have had ample time to update their
TLSA records you should not omit any standard digests, just arrange
them in order from strongest to weakest. </p>
<p> When for a particular combination of "certificate usage" and
"selector" the TLSA RRset contains a well-formed record with a
matching type of "0", i.e. a full value of the associated certificate
or public key, the Postfix SMTP client will ignore all other matching
types for the same certificate usage and selector. In this case
the first algorithm listed in tls_dane_digests will be used to
compute a digest of the full value, which will then be used to match
certificates or public keys in the server's certificate chain. </p>
"selector" the TLSA RRset contains records with more than one digest
matching type, the tls_dane_digest_agility parameter determines
whether all the RRs are used, or only those with the most preferred
digest matching type. </p>
<p> Otherwise, when for a particular combination of "certificate
usage" and "selector" the TLSA RRset contains a records with more
than one non-zero matching type, i.e. multiple digest algorithms,
only records with the highest preference digest are used after
discarding any records with an incorrect digest length as unusable. </p>
<p> The tls_dane_trust_anchor_digest_enable parameter controls
whether any digest TLSA records are acceptable in usage "2" (trust
anchor assertion) TLSA records. </p>
<p> This strategy ensures that the strongest digest supported by
both the Postfix SMTP client and the remote server is used, and
weaker digests are ignored. This supports non-disruptive deprecation
of outdated digest algorithms. </p>
<p> The strategy requires that when a TLSA RRset provides association
data for multiple certificates or public keys, all RRs with the same
"certificate usage" and "selector" be published with the same set
of digests. In particular, during key rotation, when a certificate
or public key is being replaced with another (and both are published
during the transition) both the old and the new certificate MUST be
specified with the same set of digests. One can change the list of
digest algorithms later, once old keys are retired. At any given
time change either the list of digests without changing the list of
certificates or public keys or the list of certificates or public
keys without changing the list of digests. </p>
<p> It is expected that this algorithm agility mechanism will be
published in a standards track RFC for SMTP with DANE, and perhaps
in an eventual update to RFC 6698. </p>
<p> This feature is available in Postfix 2.11. </p>
<p> This feature is available in Postfix 2.11 and later. </p>

View File

@ -208,11 +208,12 @@ extern int dns_rr_eq_sa(DNS_RR *, struct sockaddr *);
* dns_lookup.c
*/
extern int dns_lookup_r(const char *, unsigned, unsigned, DNS_RR **,
VSTRING *, VSTRING *, int *);
VSTRING *, VSTRING *, int *);
extern int dns_lookup_rl(const char *, unsigned, DNS_RR **, VSTRING *,
VSTRING *, int *, int,...);
VSTRING *, int *, int,...);
extern int dns_lookup_rv(const char *, unsigned, DNS_RR **, VSTRING *,
VSTRING *, int *, int, unsigned *);
VSTRING *, int *, int, unsigned *);
#define dns_lookup(name, type, rflags, list, fqdn, why) \
dns_lookup_r((name), (type), (rflags), (list), (fqdn), (why), (int *) 0)
#define dns_lookup_l(name, rflags, list, fqdn, why, lflags, ...) \

View File

@ -312,6 +312,7 @@ tests: tok822_test mime_tests strip_addr_test tok822_limit_test \
xtext_test scache_multi_test ehlo_mask_test \
namadr_list_test mail_conf_time_test header_body_checks_tests \
mail_version_test server_acl_test resolve_local_test maps_test
safe_ultostr_test
mime_tests: mime_test mime_nest mime_8bit mime_dom mime_trunc mime_cvt \
mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3 mime_garb4
@ -516,6 +517,11 @@ mail_conf_time_test: mail_conf_time mail_conf_time.ref
diff mail_conf_time.ref mail_conf_time.tmp
rm -f mail_conf_time.tmp
safe_ultostr_test: safe_ultostr safe_ultostr.in safe_ultostr.ref
./safe_ultostr <safe_ultostr.in >safe_ultostr.tmp 2>&1
diff safe_ultostr.ref safe_ultostr.tmp
rm -f safe_ultostr.tmp
header_body_checks_null_test: header_body_checks header_body_checks_null.ref
./header_body_checks "" "" "" "" \
<mime_test.in >header_body_checks_null.tmp 2>&1

View File

@ -3103,6 +3103,16 @@ extern char *var_tls_ssl_options;
#define DEF_TLS_BC_PKEY_FPRINT 0
extern bool var_tls_bc_pkey_fprint;
/*
* Ordered list of DANE digest algorithms.
*/
#define TLS_DANE_AGILITY_OFF "off"
#define TLS_DANE_AGILITY_ON "on"
#define TLS_DANE_AGILITY_MAYBE "maybe"
#define VAR_TLS_DANE_AGILITY "tls_dane_digest_agility"
#define DEF_TLS_DANE_AGILITY TLS_DANE_AGILITY_ON
extern char *var_tls_dane_agility;
/*
* Ordered list of DANE digest algorithms.
*/
@ -3113,13 +3123,11 @@ extern char *var_tls_dane_digests;
/*
* External interface for enabling trust-anchor digests, which are risky
* when the corresponding certificate is missing from the peer chain (this
* can't happend with the leaf certificate).
* can't happen with the leaf certificate).
*/
#define TLS_DANE_CC "ca-constraint"
#define TLS_DANE_TAA "trust-anchor-assertion"
#define VAR_TLS_DANE_TA_DGST "tls_dane_trust_anchor_digest_enable"
#define DEF_TLS_DANE_TA_DGST TLS_DANE_TAA
extern char *var_tls_dane_ta_dgst;
#define VAR_TLS_DANE_TAA_DGST "tls_dane_trust_anchor_digest_enable"
#define DEF_TLS_DANE_TAA_DGST 1
extern bool var_tls_dane_taa_dgst;
/*
* Sendmail-style mail filter support.

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 "20131126"
#define MAIL_RELEASE_DATE "20131217"
#define MAIL_VERSION_NUMBER "2.11"
#ifdef SNAPSHOT

View File

@ -26,7 +26,7 @@
/* that it does not drag in all the LDAP, SQL and other map
/* lookup client code into programs that don't need it.
/*
/* Each pattern is of the form "name.type" or "type", where
/* Each pattern is of the form "name/type" or "type", where
/* "name" and "type" are the first two fields of a master.cf
/* entry. Patterns are separated by whitespace and/or commas.
/* Matches are case insensitive. Patterns are matched in the
@ -34,6 +34,9 @@
/* match. In order to reverse the result of a pattern match,
/* precede a pattern with an exclamation point (!).
/*
/* For backwards compatibility, the form name.type is still
/* supported.
/*
/* match_service_init() parses the pattern list. The result
/* must be passed to match_service_match() or match_service_free().
/*
@ -78,6 +81,19 @@
#include <stringops.h>
#include <match_service.h>
/* match_service_compat - backwards compatibility */
static void match_service_compat(ARGV *argv)
{
char **cpp;
char *cp;
for (cpp = argv->argv; *cpp; cpp++) {
if (strrchr(*cpp, '/') == 0 && (cp = strrchr(*cpp, '.')) != 0)
*cp = '/';
}
}
/* match_service_init - initialize pattern list */
ARGV *match_service_init(const char *patterns)
@ -92,6 +108,7 @@ ARGV *match_service_init(const char *patterns)
argv_add(list, item, (char *) 0);
argv_terminate(list);
myfree(saved_patterns);
match_service_compat(list);
return (list);
}
@ -105,6 +122,7 @@ ARGV *match_service_init_argv(char **patterns)
for (cpp = patterns; *cpp; cpp++)
argv_add(list, *cpp, (char *) 0);
argv_terminate(list);
match_service_compat(list);
return (list);
}
@ -127,8 +145,8 @@ int match_service_match(ARGV *list, const char *name_type)
/*
* Sanity check.
*/
if ((type = strrchr(name_type, '.')) == 0 || *++type == 0)
msg_panic("%s: malformed service: \"%s\"; need \"name.type\" format",
if ((type = strrchr(name_type, '/')) == 0 || *++type == 0)
msg_panic("%s: malformed service: \"%s\"; need \"name/type\" format",
myname, name_type);
/*
@ -139,7 +157,7 @@ int match_service_match(ARGV *list, const char *name_type)
msg_info("%s: %s ~? %s", myname, name_type, pattern);
for (match = 1; *pattern == '!'; pattern++)
match = !match;
if (strcasecmp(strchr(pattern, '.') ? name_type : type, pattern) == 0) {
if (strcasecmp(strchr(pattern, '/') ? name_type : type, pattern) == 0) {
if (msg_verbose)
msg_info("%s: %s: found match", myname, name_type);
return (match);

View File

@ -97,7 +97,7 @@ static unsigned char safe_chars[] =
/* safe_ultostr - convert unsigned long to safe alphanumerical string */
char *safe_ultostr(VSTRING *buf, unsigned long ulval, int base,
int padlen, int padchar)
int padlen, int padchar)
{
const char *myname = "safe_ultostr";
char *start;
@ -171,6 +171,8 @@ unsigned long safe_strtoul(const char *start, char **end, int base)
/*
* Skip leading whitespace. We don't implement sign/base prefixes.
*/
if (end)
*end = (char *) start;
while (ISSPACE(*start))
++start;
@ -178,13 +180,7 @@ unsigned long safe_strtoul(const char *start, char **end, int base)
* Start the conversion.
*/
errno = 0;
for (cp = (unsigned char *) start; *cp; cp++) {
/* Return (0, EINVAL) if no conversion was made. */
if ((char_val = char_map[*cp]) >= base) {
if (cp == (unsigned char *) start)
errno = EINVAL;
break;
}
for (cp = (unsigned char *) start; (char_val = char_map[*cp]) < base; cp++) {
/* Return (ULONG_MAX, ERANGE) if the result is too large. */
if (sum > div_limit
|| (sum == div_limit && char_val > mod_limit)) {
@ -197,7 +193,10 @@ unsigned long safe_strtoul(const char *start, char **end, int base)
}
sum = sum * base + char_val;
}
if (end)
/* Return (0, EINVAL) after no conversion. Test moved here 20131209. */
if (cp == (unsigned char *) start)
errno = EINVAL;
else if (end)
*end = (char *) cp;
return (sum);
}
@ -225,6 +224,16 @@ int main(int unused_argc, char **unused_argv)
#define strtoul strtol
#endif
/*
* Hard-coded string-to-number test.
*/
ulval2 = safe_strtoul(" ", &junk, 10);
if (*junk == 0 || errno != EINVAL)
msg_warn("input=' ' result=%lu errno=%m", ulval2);
/*
* Configurable number-to-string-to-number test.
*/
while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
ch = 0;
if (sscanf(STR(buf), "%lu %d%c", &ulval, &base, &ch) != 2 || ch) {

View File

@ -0,0 +1,4 @@
4294967295 2
4294967295 10
4294967295 16
4294967295 52

View File

@ -0,0 +1,4 @@
4294967295 = 11111111111111111111111111111111
4294967295 = 4294967295
4294967295 = HHHHHHHH
4294967295 = CHPgSv

View File

@ -532,7 +532,8 @@
/* The location of the Postfix top-level queue directory.
/* .IP "\fBrecipient_delimiter (empty)\fR"
/* The set of characters that can separate a user name from its
/* address extension (user+foo).
/* extension (example: user+foo), or a .forward file name from its
/* extension (example: .forward+foo).
/* .IP "\fBrequire_home_directory (no)\fR"
/* Require that a \fBlocal\fR(8) recipient's home directory exists
/* before mail delivery is attempted.

View File

@ -294,7 +294,7 @@ MASTER_SERV *get_master_ent()
continue;
name = cp;
transport = get_str_ent(&bufp, "transport type", (char *) 0);
vstring_sprintf(junk, "%s.%s", name, transport);
vstring_sprintf(junk, "%s/%s", name, transport);
if (match_service_match(master_disable, vstring_str(junk)) == 0)
break;
}

View File

@ -358,7 +358,7 @@ static sfsistat test_eom(SMFICTX *ctx)
#endif
{
int count;
char *args;
char *args;
for (count = 0; count < add_rcpt_count; count++) {
if ((args = strchr(add_rcpt[count], ' ')) != 0) {

View File

@ -395,7 +395,8 @@
/* The location of the Postfix top-level queue directory.
/* .IP "\fBrecipient_delimiter (empty)\fR"
/* The set of characters that can separate a user name from its
/* address extension (user+foo).
/* extension (example: user+foo), or a .forward file name from its
/* extension (example: .forward+foo).
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"

View File

@ -2,11 +2,11 @@ SHELL = /bin/sh
SRCS = postconf.c postconf_builtin.c postconf_edit.c postconf_main.c \
postconf_master.c postconf_misc.c postconf_node.c postconf_other.c \
postconf_service.c postconf_unused.c postconf_user.c postconf_dbms.c \
postconf_lookup.c
postconf_lookup.c postconf_match.c postconf_print.c
OBJS = postconf.o postconf_builtin.o postconf_edit.o postconf_main.o \
postconf_master.o postconf_misc.o postconf_node.o postconf_other.o \
postconf_service.o postconf_unused.o postconf_user.o postconf_dbms.o \
postconf_lookup.o
postconf_lookup.o postconf_match.o postconf_print.o
HDRS = postconf.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
@ -45,7 +45,9 @@ test: $(TESTPROG)
tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \
test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 \
test22 test23 test24 test25 test26 test27 test28 test29 test30 test4b \
test31 test32 test33 test34 test35 test36 test37 test39 test40
test31 test32 test33 test34 test35 test36 test37 test39 test40 test41 \
test42 test43 test44 test45 test46 test47 test48 test49 test50 test51 \
test52 test53 test54 test55 test56
root_tests:
@ -169,7 +171,7 @@ test9: $(PROG) test9.ref
touch main.cf master.cf
echo foo inet - n n - 0 spawn >> master.cf
echo bar unix - n n - 0 spawn >> master.cf
./$(PROG) -c . -M inet >test9.tmp 2>&1
./$(PROG) -c . -M '*'/inet >test9.tmp 2>&1
diff test9.ref test9.tmp
rm -f main.cf master.cf test9.tmp
@ -178,7 +180,7 @@ test10: $(PROG) test10.ref
touch main.cf master.cf
echo foo inet - n n - 0 spawn >> master.cf
echo bar unix - n n - 0 spawn >> master.cf
./$(PROG) -c . -M bar.inet foo.unix >test10.tmp 2>&1
./$(PROG) -c . -M bar/inet foo/unix >test10.tmp 2>&1
diff test10.ref test10.tmp
rm -f main.cf master.cf test10.tmp
@ -513,7 +515,7 @@ test39: $(PROG) test39.ref
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc . unix >test39.tmp 2>&1
./$(PROG) -Mfc . '*'/unix >test39.tmp 2>&1
diff test39.ref test39.tmp
rm -f main.cf master.cf test39.tmp
@ -524,10 +526,183 @@ test40: $(PROG) test40.ref
echo ' -voaaa=bbb' >> master.cf
echo ' -vo ccc=$$aaa' >> master.cf
echo ' -v -oddd=$$ccc' >> master.cf
./$(PROG) -Mfxc . unix >test40.tmp 2>&1
./$(PROG) -Mfxc . '*'/unix >test40.tmp 2>&1
diff test40.ref test40.tmp
rm -f main.cf master.cf test40.tmp
test41: $(PROG) test41.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Pc . bar/unix/xxx=yyy bar/unix/aaa=bbb >test41.tmp 2>&1
./$(PROG) -Mfc. >>test41.tmp 2>&1
./$(PROG) -Pc . bar/unix/xxx=YYY bar/unix/aaa=BBB >>test41.tmp 2>&1
./$(PROG) -Mfc. >>test41.tmp 2>&1
./$(PROG) -Pc . >>test41.tmp 2>&1
diff test41.ref test41.tmp
rm -f main.cf master.cf test41.tmp
test42: $(PROG) test42.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Pc . bar/unix/xxx=yyy bar/unix/aaa=bbb >test42.tmp 2>&1
./$(PROG) -Mfc. >>test42.tmp 2>&1
./$(PROG) -Pc . >>test42.tmp 2>&1
./$(PROG) -PXc. bar/unix/xxx bar/unix/aaa >>test42.tmp 2>&1
./$(PROG) -Mfc. >>test42.tmp 2>&1
diff test42.ref test42.tmp
rm -f main.cf master.cf test42.tmp
test43: $(PROG) test43.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Fc . bar/unix/chroot=y bar/unix/command='aa -stuffobb=cc dd' >test43.tmp 2>&1
./$(PROG) -Mfc. >>test43.tmp 2>&1
diff test43.ref test43.tmp
rm -f main.cf master.cf test43.tmp
test44: $(PROG) test44.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar unix - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mc . bar/unix='xx inet - n n - 0 aa -stuffobb=cc dd' >test44.tmp 2>&1
./$(PROG) -Mfc. >>test44.tmp 2>&1
diff test44.ref test44.tmp
rm -f main.cf master.cf test44.tmp
test45: $(PROG) test45.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar xxxx - n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc. >test45.tmp 2>&1 || true
diff test45.ref test45.tmp
rm -f main.cf master.cf test45.tmp
test46: $(PROG) test46.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet X n n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc. >test46.tmp 2>&1 || true
diff test46.ref test46.tmp
rm -f main.cf master.cf test46.tmp
test47: $(PROG) test47.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - X n - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc. >test47.tmp 2>&1 || true
diff test47.ref test47.tmp
rm -f main.cf master.cf test47.tmp
test48: $(PROG) test48.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n X - 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc. >test48.tmp 2>&1 || true
diff test48.ref test48.tmp
rm -f main.cf master.cf test48.tmp
test49: $(PROG) test49.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n X 0 other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc. >test49.tmp 2>&1 || true
diff test49.ref test49.tmp
rm -f main.cf master.cf test49.tmp
test50: $(PROG) test50.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n - X other >> master.cf
echo baz unix - n n - 0 other >> master.cf
./$(PROG) -Mfc. >test50.tmp 2>&1 || true
diff test50.ref test50.tmp
rm -f main.cf master.cf test50.tmp
test51: $(PROG) test51.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n -? 0 other >> master.cf
echo bar inet - n n X? 0 other >> master.cf
echo baz unix - n n 0? 0 other >> master.cf
./$(PROG) -Mfc. >test51.tmp 2>&1 || true
diff test51.ref test51.tmp
rm -f main.cf master.cf test51.tmp
test52: $(PROG) test52.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
./$(PROG) -MXc. bar/inet foo/unix xxx/yyy
./$(PROG) -Mfc. >test52.tmp 2>&1 || true
diff test52.ref test52.tmp
rm -f main.cf master.cf test52.tmp
test53: $(PROG) test53.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
./$(PROG) -M#c. bar/inet xxx/yyy
diff test53.ref master.cf
rm -f main.cf master.cf test53.tmp
test54: $(PROG) test54.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
./$(PROG) -M#c. bar/inet foo/unix
diff test54.ref master.cf
rm -f main.cf master.cf test54.tmp
test55: $(PROG) test55.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n 0 0 other >> master.cf
echo baz unix - n n 0 0 other >> master.cf
./$(PROG) -M#c. bar/inet baz/unix
diff test55.ref master.cf
rm -f main.cf master.cf test55.tmp
test56: $(PROG) test56.ref
rm -f main.cf master.cf
touch main.cf master.cf
echo foo unix - n n - 0 other >> master.cf
echo bar inet - n n 0 0 other >> master.cf
echo " -o first" >> master.cf
echo " -o second" >> master.cf
echo baz unix - n n 0 0 other >> master.cf
./$(PROG) -M#c. bar/inet xxx/yyy
diff test56.ref master.cf
rm -f main.cf master.cf test56.tmp
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@ -568,6 +743,7 @@ postconf.o: ../../include/msg.h
postconf.o: ../../include/msg_vstream.h
postconf.o: ../../include/myflock.h
postconf.o: ../../include/mymalloc.h
postconf.o: ../../include/name_code.h
postconf.o: ../../include/name_mask.h
postconf.o: ../../include/stringops.h
postconf.o: ../../include/sys_defs.h
@ -593,6 +769,7 @@ postconf_builtin.o: ../../include/msg.h
postconf_builtin.o: ../../include/myflock.h
postconf_builtin.o: ../../include/mymalloc.h
postconf_builtin.o: ../../include/mynetworks.h
postconf_builtin.o: ../../include/name_code.h
postconf_builtin.o: ../../include/server_acl.h
postconf_builtin.o: ../../include/stringops.h
postconf_builtin.o: ../../include/sys_defs.h
@ -634,6 +811,7 @@ postconf_dbms.o: ../../include/mac_expand.h
postconf_dbms.o: ../../include/mac_parse.h
postconf_dbms.o: ../../include/mail_conf.h
postconf_dbms.o: ../../include/myflock.h
postconf_dbms.o: ../../include/name_code.h
postconf_dbms.o: ../../include/split_at.h
postconf_dbms.o: ../../include/stringops.h
postconf_dbms.o: ../../include/sys_defs.h
@ -650,7 +828,9 @@ postconf_edit.o: ../../include/mail_params.h
postconf_edit.o: ../../include/msg.h
postconf_edit.o: ../../include/myflock.h
postconf_edit.o: ../../include/mymalloc.h
postconf_edit.o: ../../include/name_code.h
postconf_edit.o: ../../include/readlline.h
postconf_edit.o: ../../include/split_at.h
postconf_edit.o: ../../include/stringops.h
postconf_edit.o: ../../include/sys_defs.h
postconf_edit.o: ../../include/vbuf.h
@ -668,6 +848,7 @@ postconf_lookup.o: ../../include/mail_conf.h
postconf_lookup.o: ../../include/msg.h
postconf_lookup.o: ../../include/myflock.h
postconf_lookup.o: ../../include/mymalloc.h
postconf_lookup.o: ../../include/name_code.h
postconf_lookup.o: ../../include/stringops.h
postconf_lookup.o: ../../include/sys_defs.h
postconf_lookup.o: ../../include/vbuf.h
@ -685,6 +866,7 @@ postconf_main.o: ../../include/mail_params.h
postconf_main.o: ../../include/msg.h
postconf_main.o: ../../include/myflock.h
postconf_main.o: ../../include/mymalloc.h
postconf_main.o: ../../include/name_code.h
postconf_main.o: ../../include/readlline.h
postconf_main.o: ../../include/stringops.h
postconf_main.o: ../../include/sys_defs.h
@ -697,11 +879,13 @@ postconf_master.o: ../../include/argv.h
postconf_master.o: ../../include/dict.h
postconf_master.o: ../../include/htable.h
postconf_master.o: ../../include/mail_params.h
postconf_master.o: ../../include/match_service.h
postconf_master.o: ../../include/master_proto.h
postconf_master.o: ../../include/msg.h
postconf_master.o: ../../include/myflock.h
postconf_master.o: ../../include/mymalloc.h
postconf_master.o: ../../include/name_code.h
postconf_master.o: ../../include/readlline.h
postconf_master.o: ../../include/split_at.h
postconf_master.o: ../../include/stringops.h
postconf_master.o: ../../include/sys_defs.h
postconf_master.o: ../../include/vbuf.h
@ -709,6 +893,20 @@ postconf_master.o: ../../include/vstream.h
postconf_master.o: ../../include/vstring.h
postconf_master.o: postconf.h
postconf_master.o: postconf_master.c
postconf_match.o: ../../include/argv.h
postconf_match.o: ../../include/dict.h
postconf_match.o: ../../include/htable.h
postconf_match.o: ../../include/msg.h
postconf_match.o: ../../include/myflock.h
postconf_match.o: ../../include/mymalloc.h
postconf_match.o: ../../include/name_code.h
postconf_match.o: ../../include/split_at.h
postconf_match.o: ../../include/sys_defs.h
postconf_match.o: ../../include/vbuf.h
postconf_match.o: ../../include/vstream.h
postconf_match.o: ../../include/vstring.h
postconf_match.o: postconf.h
postconf_match.o: postconf_match.c
postconf_misc.o: ../../include/argv.h
postconf_misc.o: ../../include/dict.h
postconf_misc.o: ../../include/htable.h
@ -716,6 +914,7 @@ postconf_misc.o: ../../include/mail_conf.h
postconf_misc.o: ../../include/mail_params.h
postconf_misc.o: ../../include/myflock.h
postconf_misc.o: ../../include/mymalloc.h
postconf_misc.o: ../../include/name_code.h
postconf_misc.o: ../../include/safe.h
postconf_misc.o: ../../include/sys_defs.h
postconf_misc.o: ../../include/vbuf.h
@ -729,6 +928,7 @@ postconf_node.o: ../../include/htable.h
postconf_node.o: ../../include/msg.h
postconf_node.o: ../../include/myflock.h
postconf_node.o: ../../include/mymalloc.h
postconf_node.o: ../../include/name_code.h
postconf_node.o: ../../include/sys_defs.h
postconf_node.o: ../../include/vbuf.h
postconf_node.o: ../../include/vstream.h
@ -740,6 +940,7 @@ postconf_other.o: ../../include/dict.h
postconf_other.o: ../../include/htable.h
postconf_other.o: ../../include/mbox_conf.h
postconf_other.o: ../../include/myflock.h
postconf_other.o: ../../include/name_code.h
postconf_other.o: ../../include/sys_defs.h
postconf_other.o: ../../include/vbuf.h
postconf_other.o: ../../include/vstream.h
@ -747,6 +948,18 @@ postconf_other.o: ../../include/vstring.h
postconf_other.o: ../../include/xsasl.h
postconf_other.o: postconf.h
postconf_other.o: postconf_other.c
postconf_print.o: ../../include/argv.h
postconf_print.o: ../../include/dict.h
postconf_print.o: ../../include/htable.h
postconf_print.o: ../../include/msg.h
postconf_print.o: ../../include/myflock.h
postconf_print.o: ../../include/name_code.h
postconf_print.o: ../../include/sys_defs.h
postconf_print.o: ../../include/vbuf.h
postconf_print.o: ../../include/vstream.h
postconf_print.o: ../../include/vstring.h
postconf_print.o: postconf.h
postconf_print.o: postconf_print.c
postconf_service.o: ../../include/argv.h
postconf_service.o: ../../include/dict.h
postconf_service.o: ../../include/htable.h
@ -754,6 +967,7 @@ postconf_service.o: ../../include/mail_params.h
postconf_service.o: ../../include/msg.h
postconf_service.o: ../../include/myflock.h
postconf_service.o: ../../include/mymalloc.h
postconf_service.o: ../../include/name_code.h
postconf_service.o: ../../include/stringops.h
postconf_service.o: ../../include/sys_defs.h
postconf_service.o: ../../include/vbuf.h
@ -768,6 +982,7 @@ postconf_unused.o: ../../include/mail_conf.h
postconf_unused.o: ../../include/mail_params.h
postconf_unused.o: ../../include/msg.h
postconf_unused.o: ../../include/myflock.h
postconf_unused.o: ../../include/name_code.h
postconf_unused.o: ../../include/sys_defs.h
postconf_unused.o: ../../include/vbuf.h
postconf_unused.o: ../../include/vstream.h
@ -784,6 +999,7 @@ postconf_user.o: ../../include/mail_params.h
postconf_user.o: ../../include/msg.h
postconf_user.o: ../../include/myflock.h
postconf_user.o: ../../include/mymalloc.h
postconf_user.o: ../../include/name_code.h
postconf_user.o: ../../include/stringops.h
postconf_user.o: ../../include/sys_defs.h
postconf_user.o: ../../include/vbuf.h

View File

@ -11,15 +11,40 @@
/* [\fB-C \fIclass,...\fR] [\fIparameter ...\fR]
/*
/* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIparameter=value ...\fR]
/* \fIparameter=value ...\fR
/*
/* \fBpostconf\fR [\fB-#vX\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIparameter ...\fR]
/* \fIparameter ...\fR
/*
/* \fBManaging master.cf:\fR
/* \fBManaging master.cf service entries:\fR
/*
/* \fBpostconf\fR [\fB-fMovx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIservice ...\fR]
/* [\fIservice\fR[\fB/\fItype\fR]\fI ...\fR]
/*
/* \fBpostconf\fR [\fB-eMv\fR] [\fB-c \fIconfig_dir\fR]
/* \fIservice\fB/\fItype=value ...\fR
/*
/* \fBpostconf\fR [\fB-#MvX\fR] [\fB-c \fIconfig_dir\fR]
/* \fIservice\fB/\fItype ...\fR
/*
/* \fBManaging master.cf service fields:\fR
/*
/* \fBpostconf\fR [\fB-fFovx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR]
/*
/* \fBpostconf\fR [\fB-eFv\fR] [\fB-c \fIconfig_dir\fR]
/* \fIservice\fB/\fItype\fB/\fIfield=value ...\fR
/*
/* \fBManaging master.cf service parameters:\fR
/*
/* \fBpostconf\fR [\fB-fPovx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR]
/*
/* \fBpostconf\fR [\fB-ePv\fR] [\fB-c \fIconfig_dir\fR]
/* \fIservice\fB/\fItype\fB/\fIparameter=value ...\fR
/*
/* \fBpostconf\fR [\fB-PXv\fR] [\fB-c \fIconfig_dir\fR]
/* \fIservice\fB/\fItype\fB/\fIparameter ...\fR
/*
/* \fBManaging bounce message templates:\fR
/*
@ -108,21 +133,56 @@
/* (Postfix 2.9 and later).
/* .IP \fB-e\fR
/* Edit the \fBmain.cf\fR configuration file, and update
/* parameter settings with the "\fIname=value\fR" pairs
/* on the \fBpostconf\fR(1) command line. The file is copied
/* to a temporary file then renamed into place.
/* Specify quotes to protect special characters and whitespace
/* on the \fBpostconf\fR(1) command line.
/* parameter settings with the "\fIname=value\fR" pairs on the
/* \fBpostconf\fR(1) command line.
/*
/* The \fB-e\fR is no longer needed with Postfix version 2.8
/* and later.
/* With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
/* and replace one or more service entries with new values as
/* specified with "\fIservice/type=value\fR" on the \fBpostconf\fR(1)
/* command line.
/*
/* With \fB-F\fR, edit the \fBmaster.cf\fR configuration file,
/* and replace one or more service fields with new values as
/* specied with "\fIservice/type/field=value\fR" on the
/* \fBpostconf\fR(1) command line. Currently, the "command"
/* field contains the command name and command arguments. this
/* may change in the near future, so that the "command" field
/* contains only the command name, and a new "arguments"
/* pseudofield contains the command arguments.
/*
/* With \fB-P\fR, edit the \fBmaster.cf\fR configuration file,
/* and add or update one or more service parameter settings
/* (-o parameter=value settings) with new values as specied
/* with "\fIservice/type/parameter=value\fR" on the \fBpostconf\fR(1)
/* command line.
/*
/* In all cases the file is copied to a temporary file then
/* renamed into place. Specify quotes to protect special
/* characters and whitespace on the \fBpostconf\fR(1) command
/* line.
/*
/* The \fB-e\fR option is no longer needed with Postfix version
/* 2.8 and later.
/* .IP \fB-f\fR
/* Fold long lines when printing \fBmain.cf\fR or \fBmaster.cf\fR
/* configuration file entries, for human readability.
/*
/* This feature is available with Postfix 2.9 and later.
/* .IP \fB-F\fR
/* Show \fBmaster.cf\fR per-entry field settings (by default
/* all services and all fields), formatted as one
/* "\fIservice/type/field=value\fR" per line. Specify \fB-Ff\fR
/* to fold long lines.
/*
/* Specify one or more "\fIservice/type/field\fR" instances
/* on the \fBpostconf\fR(1) command line to limit the output
/* to fields of interest. Trailing parameter name or service
/* type fields that are omitted will be handled as "*" wildcard
/* fields.
/*
/* This feature is available with Postfix 2.11 and later.
/* .IP \fB-h\fR
/* Show \fBmain.cf\fR parameter values without the "\fIname\fR
/* Show parameter or attribute values without the "\fIname\fR
/* = " label that normally precedes the value.
/* .IP \fB-l\fR
/* List the names of all supported mailbox locking methods.
@ -133,21 +193,22 @@
/* This locking method is available on systems with a BSD
/* compatible library.
/* .IP \fBfcntl\fR
/* A kernel-based advisory locking method for local and remote files.
/* A kernel-based advisory locking method for local and remote
/* files.
/* .IP \fBdotlock\fR
/* An application-level locking method. An application locks a file
/* named \fIfilename\fR by creating a file named \fIfilename\fB.lock\fR.
/* The application is expected to remove its own lock file, as well as
/* stale lock files that were left behind after abnormal program
/* termination.
/* An application-level locking method. An application locks
/* a file named \fIfilename\fR by creating a file named
/* \fIfilename\fB.lock\fR. The application is expected to
/* remove its own lock file, as well as stale lock files that
/* were left behind after abnormal program termination.
/* .RE
/* .IP \fB-m\fR
/* List the names of all supported lookup table types. In Postfix
/* configuration files,
/* lookup tables are specified as \fItype\fB:\fIname\fR, where
/* \fItype\fR is one of the types listed below. The table \fIname\fR
/* syntax depends on the lookup table type as described in the
/* DATABASE_README document.
/* List the names of all supported lookup table types. In
/* Postfix configuration files, lookup tables are specified
/* as \fItype\fB:\fIname\fR, where \fItype\fR is one of the
/* types listed below. The table \fIname\fR syntax depends on
/* the lookup table type as described in the DATABASE_README
/* document.
/* .RS
/* .IP \fBbtree\fR
/* A sorted, balanced tree structure. Available on systems
@ -210,53 +271,78 @@
/* .IP "\fBsqlite\fR (read-only)"
/* SQLite database. This is described in \fBsqlite_table\fR(5).
/* .IP "\fBstatic\fR (read-only)"
/* A table that always returns its name as lookup result. For example,
/* \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup
/* result.
/* A table that always returns its name as lookup result. For
/* example, \fBstatic:foobar\fR always returns the string
/* \fBfoobar\fR as lookup result.
/* .IP "\fBtcp\fR (read-only)"
/* TCP/IP client. The protocol is described in \fBtcp_table\fR(5).
/* .IP "\fBtexthash\fR (read-only)"
/* Produces similar results as hash: files, except that you don't
/* need to run the \fBpostmap\fR(1) command before you can use the file,
/* and that it does not detect changes after the file is read.
/* Produces similar results as hash: files, except that you
/* don't need to run the \fBpostmap\fR(1) command before you
/* can use the file, and that it does not detect changes after
/* the file is read.
/* .IP "\fBunix\fR (read-only)"
/* A limited view of the UNIX authentication database. The
/* following tables are implemented:
/* .RS
/*. IP \fBunix:passwd.byname\fR
/* The table is the UNIX password database. The key is a login name.
/* The result is a password file entry in \fBpasswd\fR(5) format.
/* The table is the UNIX password database. The key is a login
/* name. The result is a password file entry in \fBpasswd\fR(5)
/* format.
/* .IP \fBunix:group.byname\fR
/* The table is the UNIX group database. The key is a group name.
/* The result is a group file entry in \fBgroup\fR(5) format.
/* The table is the UNIX group database. The key is a group
/* name. The result is a group file entry in \fBgroup\fR(5)
/* format.
/* .RE
/* .RE
/* .IP
/* Other table types may exist depending on how Postfix was built.
/* Other table types may exist depending on how Postfix was
/* built.
/* .IP \fB-M\fR
/* Show \fBmaster.cf\fR file contents instead of \fBmain.cf\fR
/* file contents.
/* Specify \fB-Mf\fR to fold long lines for human readability.
/* file contents. Specify \fB-Mf\fR to fold long lines for
/* human readability.
/*
/* If \fIservice ...\fR is specified, only the matching services
/* will be output. For example, "\fBpostconf -Mf inet\fR"
/* will output all services that listen on the network.
/* Specify zero or more arguments, each with a \fIservice-name\fR
/* or \fIservice-name/service-type\fR pair, where \fIservice-name\fR
/* is the first field of a master.cf entry and \fIservice-type\fR
/* is one of (\fBinet\fR, \fBunix\fR, \fBfifo\fR, or \fBpass\fR).
/*
/* Specify zero or more arguments, each with a \fIservice-type\fR
/* name (\fBinet\fR, \fBunix\fR, \fBfifo\fR, or \fBpass\fR)
/* or with a \fIservice-name.service-type\fR pair, where
/* \fIservice-name\fR is the first field of a master.cf entry.
/* If \fIservice-name\fR or \fIservice-name/service-type\fR
/* is specified, only the matching master.cf entries will be
/* output. For example, "\fBpostconf -Mf smtp\fR" will output
/* all services named "smtp", and "\fBpostconf -Mf smtp/inet\fR"
/* will output only the smtp service that listens on the
/* network. Trailing service type fields that are omitted
/* will be handled as "*" wildcard fields.
/*
/* This feature is available with Postfix 2.9 and later.
/* This feature is available with Postfix 2.9 and later. The
/* syntax was changed from "\fIname.type\fR" to "\fIname/type\fR",
/* and "*" wildcard support was added with Postfix 2.11.
/* .IP \fB-n\fR
/* Show only configuration parameters that have explicit
/* \fIname=value\fR settings in \fBmain.cf\fR.
/* Specify \fB-nf\fR to fold long lines for human readability
/* (Postfix 2.9 and later).
/* \fIname=value\fR settings in \fBmain.cf\fR. Specify \fB-nf\fR
/* to fold long lines for human readability (Postfix 2.9 and
/* later).
/* .IP "\fB-o \fIname=value\fR"
/* Override \fBmain.cf\fR parameter settings.
/*
/* This feature is available with Postfix 2.10 and later.
/* .IP \fB-p\fR
/* Show \fBmain.cf\fR parameter settings. This is the default.
/* .IP \fB-P\fR
/* Show \fBmaster.cf\fR service parameter settings (by default
/* all services and all parameters). formatted as one
/* "\fIservice/type/parameter=value\fR" per line. Specify
/* \fB-Pf\fR to fold long lines.
/*
/* Specify one or more "\fIservice/type/parameter\fR" instances
/* on the \fBpostconf\fR(1) command line to limit the output
/* to parameters of interest. Trailing parameter name or
/* service type fields that are omitted will be handled as "*"
/* wildcard fields.
/*
/* This feature is available with Postfix 2.11 and later.
/* .IP "\fB-t\fR [\fItemplate_file\fR]"
/* Display the templates for text that appears at the beginning
/* of delivery status notification (DSN) messages, without
@ -273,34 +359,59 @@
/*
/* This feature is available with Postfix 2.3 and later.
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* options make the software increasingly verbose.
/* Enable verbose logging for debugging purposes. Multiple
/* \fB-v\fR options make the software increasingly verbose.
/* .IP \fB-x\fR
/* Expand \fI$name\fR in \fBmain.cf\fR or \fBmaster.cf\fR
/* parameter values. The expansion is recursive.
/*
/* This feature is available with Postfix 2.10 and later.
/* .IP \fB-X\fR
/* Edit the \fBmain.cf\fR configuration file, and remove
/* the parameters named on the \fBpostconf\fR(1) command line.
/* The file is copied to a temporary file then renamed into
/* place.
/* Edit the \fBmain.cf\fR configuration file, and remove the
/* parameters named on the \fBpostconf\fR(1) command line.
/* Specify a list of parameter names, not "\fIname=value\fR"
/* pairs. There is no \fBpostconf\fR(1) command to perform
/* the reverse operation.
/* pairs.
/*
/* With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
/* and remove one or more service entries as specified with
/* "\fIservice/type\fR" on the \fBpostconf\fR(1) command line.
/*
/* With \fB-P\fR, edit the \fBmaster.cf\fR configuration file,
/* and remove one or more service parameter settings (-o
/* parameter=value settings) as specied with
/* "\fIservice/type/parameter\fR" on the \fBpostconf\fR(1)
/* command line.
/*
/* In all cases the file is copied to a temporary file then
/* renamed into place. Specify quotes to protect special
/* characters on the \fBpostconf\fR(1) command line.
/*
/* There is no \fBpostconf\fR(1) command to perform the reverse
/* operation.
/*
/* This feature is available with Postfix 2.10 and later.
/* Support for -M and -P was added with Postfix 2.11.
/* .IP \fB-#\fR
/* Edit the \fBmain.cf\fR configuration file, and comment out
/* the parameters named on the \fBpostconf\fR(1) command line,
/* so that those parameters revert to their default values.
/* The file is copied to a temporary file then renamed into
/* place.
/* Specify a list of parameter names, not "\fIname=value\fR"
/* pairs. There is no \fBpostconf\fR(1) command to perform
/* the reverse operation.
/* pairs.
/*
/* This feature is available with Postfix 2.6 and later.
/* With \fB-M\fR, edit the \fBmaster.cf\fR configuration file,
/* and comment out one or more service entries as specified
/* with "\fIservice/type\fR" on the \fBpostconf\fR(1) command
/* line.
/*
/* In all cases the file is copied to a temporary file then
/* renamed into place. Specify quotes to protect special
/* characters on the \fBpostconf\fR(1) command line.
/*
/* There is no \fBpostconf\fR(1) command to perform the reverse
/* operation.
/*
/* This feature is available with Postfix 2.6 and later. Support
/* for -M was added with Postfix 2.11.
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* ENVIRONMENT
@ -311,8 +422,8 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program.
/* The following \fBmain.cf\fR parameters are especially
/* relevant to this program.
/*
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
@ -323,28 +434,27 @@
/* Pathname of a configuration file with bounce message templates.
/* FILES
/* /etc/postfix/main.cf, Postfix configuration parameters
/* /etc/postfix/master.cf, Postfix master daemon configuraton
/* /etc/postfix/master.cf, Postfix master daemon configuration
/* SEE ALSO
/* bounce(5), bounce template file format
/* master(5), master.cf configuration file syntax
/* postconf(5), main.cf configuration file syntax
/* bounce(5), bounce template file format master(5), master.cf
/* configuration file syntax postconf(5), main.cf configuration
/* file syntax
/* README FILES
/* .ad
/* .fi
/* Use "\fBpostconf readme_directory\fR" or
/* "\fBpostconf html_directory\fR" to locate this information.
/* Use "\fBpostconf readme_directory\fR" or "\fBpostconf
/* html_directory\fR" to locate this information.
/* .na
/* .nf
/* DATABASE_README, Postfix lookup table overview
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* The Secure Mailer license must be distributed with this
/* software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/* Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown
/* Heights, NY 10598, USA
/*--*/
/* System library. */
@ -390,6 +500,153 @@ int cmd_mode = DEF_MODE;
*/
MAIL_VERSION_STAMP_DECLARE;
/*
* This program has so many command-line options that we have to implement a
* compatibility matrix to weed out the conflicting option combinations, and
* to alert the user about option combinations that have no effect.
*/
/*
* Options that are mutually-exclusive. First entry must specify the major
* modes. Other entries specify conflicts between option modifiers.
*/
static const int incompat_options[] = {
/* Major modes. */
SHOW_SASL_SERV | SHOW_SASL_CLNT | EXP_DSN_TEMPL | SHOW_LOCKS | SHOW_MAPS \
|DUMP_DSN_TEMPL | MAIN_PARAM | MASTER_ENTRY | MASTER_FIELD | MASTER_PARAM,
/* Modifiers. */
SHOW_DEFS | EDIT_CONF | SHOW_NONDEF | COMMENT_OUT | EDIT_EXCL,
FOLD_LINE | EDIT_CONF | COMMENT_OUT | EDIT_EXCL,
SHOW_EVAL | EDIT_CONF | COMMENT_OUT | EDIT_EXCL,
MAIN_OVER | SHOW_DEFS | EDIT_CONF | COMMENT_OUT | EDIT_EXCL,
HIDE_NAME | EDIT_CONF | COMMENT_OUT | EDIT_EXCL,
0,
};
/*
* Options, and the only options that they are compatible with. There must
* be one entry for each major mode. Other entries specify compatibility
* between option modifiers.
*/
static const int compat_options[][2] = {
/* Major modes. */
{SHOW_SASL_SERV, 0},
{SHOW_SASL_CLNT, 0},
{EXP_DSN_TEMPL, 0},
{SHOW_LOCKS, 0},
{SHOW_MAPS, 0,},
{DUMP_DSN_TEMPL, 0},
{MAIN_PARAM, EDIT_CONF | EDIT_EXCL | COMMENT_OUT | FOLD_LINE | HIDE_NAME \
|PARAM_CLASS | SHOW_EVAL | SHOW_DEFS | SHOW_NONDEF | MAIN_OVER},
{MASTER_ENTRY, EDIT_CONF | EDIT_EXCL | COMMENT_OUT | FOLD_LINE | MAIN_OVER \
|SHOW_EVAL},
{MASTER_FIELD, EDIT_CONF | FOLD_LINE | HIDE_NAME | MAIN_OVER | SHOW_EVAL},
{MASTER_PARAM, EDIT_CONF | EDIT_EXCL | FOLD_LINE | HIDE_NAME | MAIN_OVER \
|SHOW_EVAL},
/* Modifiers. */
{PARAM_CLASS, MAIN_PARAM | SHOW_DEFS | SHOW_NONDEF},
0,
};
/*
* Compatibility to string conversion support.
*/
static const NAME_MASK compat_names[] = {
"-a", SHOW_SASL_SERV,
"-A", SHOW_SASL_CLNT,
"-b", EXP_DSN_TEMPL,
"-C", PARAM_CLASS,
"-d", SHOW_DEFS,
"-e", EDIT_CONF,
"-f", FOLD_LINE,
"-F", MASTER_FIELD,
"-h", HIDE_NAME,
"-l", SHOW_LOCKS,
"-m", SHOW_MAPS,
"-M", MASTER_ENTRY,
"-n", SHOW_NONDEF,
"-o", MAIN_OVER,
"-p", MAIN_PARAM,
"-P", MASTER_PARAM,
"-t", DUMP_DSN_TEMPL,
"-x", SHOW_EVAL,
"-X", EDIT_EXCL,
"-#", COMMENT_OUT,
0,
};
/* usage - enumerate parameters without compatibility info */
static void usage(const char *progname)
{
msg_fatal("usage: %s"
" [-a (server SASL types)]"
" [-A (client SASL types)]"
" [-b (bounce templates)]"
" [-c config_dir]"
" [-c param_class]"
" [-d (parameter defaults)]"
" [-e (edit configuration)]"
" [-f (fold lines)]"
" [-F (master.cf fields)]"
" [-h (no names)]"
" [-l (lock types)]"
" [-m (map types)]"
" [-M (master.cf)]"
" [-n (non-default parameters)]"
" [-o name=value (override parameter value)]"
" [-p (main.cf, default)]"
" [-P (master.cf parameters)]"
" [-t (bounce templates)]"
" [-v (verbose)]"
" [-x (expand parameter values)]"
" [-X (exclude)]"
" [-# (comment-out)]"
" [name...]", progname);
}
/* check_exclusive_options - complain about mutually-exclusive options */
static void check_exclusive_options(int optval)
{
const char *myname = "check_exclusive_options";
const int *op;
int oval;
unsigned mask;
for (op = incompat_options; (oval = *op) != 0; op++) {
oval &= optval;
for (mask = ~0; (mask & oval) != 0; mask >>= 1) {
if ((mask & oval) != oval)
msg_fatal("specify one of %s",
str_name_mask(myname, compat_names, oval));
}
}
}
/* check_compat_options - complain about incompatible options */
static void check_compat_options(int optval)
{
const char *myname = "check_compat_options";
VSTRING *buf1 = vstring_alloc(10);
VSTRING *buf2 = vstring_alloc(10);
const int (*op)[2];
int excess;
for (op = compat_options; op[0][0] != 0; op++) {
if ((optval & *op[0]) != 0
&& (excess = (optval & ~((*op)[0] | (*op)[1]))) != 0)
msg_fatal("with option %s, do not specify %s",
str_name_mask_opt(buf1, myname, compat_names,
(*op)[0], NAME_MASK_NUMBER),
str_name_mask_opt(buf2, myname, compat_names, excess,
NAME_MASK_NUMBER));
}
vstring_free(buf1);
vstring_free(buf2);
}
/* main */
int main(int argc, char **argv)
@ -397,7 +654,6 @@ int main(int argc, char **argv)
int ch;
int fd;
struct stat st;
int junk;
ARGV *ext_argv = 0;
int param_class = PC_PARAM_MASK_CLASS;
static const NAME_MASK param_class_table[] = {
@ -437,7 +693,7 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "aAbc:C:deEf#hlmMno:tvxX")) > 0) {
while ((ch = GETOPT(argc, argv, "aAbc:C:deEfFhlmMno:pPtvxX#")) > 0) {
switch (ch) {
case 'a':
cmd_mode |= SHOW_SASL_SERV;
@ -446,6 +702,7 @@ int main(int argc, char **argv)
cmd_mode |= SHOW_SASL_CLNT;
break;
case 'b':
cmd_mode |= EXP_DSN_TEMPL;
if (ext_argv)
msg_fatal("specify one of -b and -t");
ext_argv = argv_alloc(2);
@ -463,16 +720,19 @@ int main(int argc, char **argv)
cmd_mode |= SHOW_DEFS;
break;
case 'e':
cmd_mode |= EDIT_MAIN;
cmd_mode |= EDIT_CONF;
break;
case 'f':
cmd_mode |= FOLD_LINE;
break;
case 'F':
cmd_mode |= MASTER_FIELD;
break;
case '#':
cmd_mode = COMMENT_OUT;
cmd_mode |= COMMENT_OUT;
break;
case 'h':
cmd_mode &= ~SHOW_NAME;
cmd_mode |= HIDE_NAME;
break;
case 'l':
cmd_mode |= SHOW_LOCKS;
@ -481,17 +741,25 @@ int main(int argc, char **argv)
cmd_mode |= SHOW_MAPS;
break;
case 'M':
cmd_mode |= SHOW_MASTER;
cmd_mode |= MASTER_ENTRY;
break;
case 'n':
cmd_mode |= SHOW_NONDEF;
break;
case 'o':
cmd_mode |= MAIN_OVER;
if (override_params == 0)
override_params = argv_alloc(2);
argv_add(override_params, optarg, (char *) 0);
break;
case 'p':
cmd_mode |= MAIN_PARAM;
break;
case 'P':
cmd_mode |= MASTER_PARAM;
break;
case 't':
cmd_mode |= DUMP_DSN_TEMPL;
if (ext_argv)
msg_fatal("specify one of -b and -t");
ext_argv = argv_alloc(2);
@ -508,27 +776,27 @@ int main(int argc, char **argv)
msg_verbose++;
break;
default:
msg_fatal("usage: %s [-a (server SASL types)] [-A (client SASL types)] [-b (bounce templates)] [-c config_dir] [-C param_class] [-d (defaults)] [-e (edit)] [-f (fold lines)] [-# (comment-out)] [-h (no names)] [-l (lock types)] [-m (map types)] [-M (master.cf)] [-n (non-defaults)] [-v] [-X (exclude)] [name...]", argv[0]);
usage(argv[0]);
}
}
/*
* Make all options explicit, before checking their compatibility.
*/
if ((cmd_mode & incompat_options[0]) == 0)
cmd_mode |= MAIN_PARAM;
if ((cmd_mode & (MAIN_PARAM | MASTER_ENTRY | MASTER_FIELD | MASTER_PARAM))
&& argv[optind] && strchr(argv[optind], '='))
cmd_mode |= EDIT_CONF;
/*
* Sanity check.
*/
junk = (cmd_mode & (SHOW_DEFS | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN | SHOW_SASL_SERV | SHOW_SASL_CLNT | COMMENT_OUT | SHOW_MASTER | EDIT_EXCL));
if (junk != 0 && ((junk != SHOW_DEFS
&& junk != SHOW_MAPS && junk != SHOW_LOCKS && junk != EDIT_MAIN
&& junk != SHOW_SASL_SERV && junk != SHOW_SASL_CLNT
&& junk != COMMENT_OUT && junk != SHOW_MASTER
&& junk != EDIT_EXCL)
|| ext_argv != 0))
msg_fatal("specify one of -a, -A, -b, -d, -e, -#, -l, -m, -M, and -X");
if ((cmd_mode & SHOW_EVAL) != 0 && junk != 0 && junk != SHOW_DEFS && junk != SHOW_MASTER)
msg_fatal("do not specify -x with -a, -A, -b, -e, -#, -l, -m, or -X");
if ((cmd_mode & SHOW_NONDEF) != 0 && junk != 0)
msg_fatal("do not specify -n with -a, -A, -b, -d, -e, -#, -l, -m, -M, or -X");
if (override_params != 0 && junk != 0 && junk != SHOW_MASTER)
msg_fatal("do not specify -o with -a, -A, -b, -d, -e, -#, -l, -m, or -X");
check_exclusive_options(cmd_mode);
check_compat_options(cmd_mode);
if ((cmd_mode & EDIT_CONF) && argc == optind)
msg_fatal("-e requires name=value argument");
/*
* Display bounce template information and exit.
@ -569,7 +837,8 @@ int main(int argc, char **argv)
/*
* If showing master.cf entries, show them and exit
*/
else if (cmd_mode & SHOW_MASTER) {
else if ((cmd_mode & (MASTER_ENTRY | MASTER_FIELD | MASTER_PARAM))
&& !(cmd_mode & (EDIT_CONF | EDIT_EXCL | COMMENT_OUT))) {
read_master(FAIL_ON_OPEN_ERROR);
read_parameters();
if (override_params)
@ -577,7 +846,12 @@ int main(int argc, char **argv)
register_builtin_parameters(basename(argv[0]), getpid());
register_service_parameters();
register_user_parameters();
show_master(VSTREAM_OUT, cmd_mode, argv + optind);
if (cmd_mode & MASTER_FIELD)
show_master_fields(VSTREAM_OUT, cmd_mode, argc - optind, argv + optind);
else if (cmd_mode & MASTER_PARAM)
show_master_params(VSTREAM_OUT, cmd_mode, argc - optind, argv + optind);
else
show_master_entries(VSTREAM_OUT, cmd_mode, argc - optind, argv + optind);
}
/*
@ -590,13 +864,16 @@ int main(int argc, char **argv)
}
/*
* Edit main.cf.
* Edit main.cf or master.cf.
*/
else if (cmd_mode & (EDIT_MAIN | COMMENT_OUT | EDIT_EXCL)) {
edit_parameters(cmd_mode, argc - optind, argv + optind);
} else if (cmd_mode == DEF_MODE
&& argv[optind] && strchr(argv[optind], '=')) {
edit_parameters(cmd_mode | EDIT_MAIN, argc - optind, argv + optind);
else if (cmd_mode & (EDIT_CONF | COMMENT_OUT | EDIT_EXCL)) {
if (optind == argc)
msg_fatal("missing service argument");
if (cmd_mode & (MASTER_ENTRY | MASTER_FIELD | MASTER_PARAM)) {
edit_master(cmd_mode, argc - optind, argv + optind);
} else {
edit_main(cmd_mode, argc - optind, argv + optind);
}
}
/*

View File

@ -19,25 +19,33 @@
#include <htable.h>
#include <argv.h>
#include <dict.h>
#include <name_code.h>
/*
* What we're supposed to be doing.
*/
#define SHOW_NONDEF (1<<0) /* show main.cf non-default settings */
#define SHOW_DEFS (1<<1) /* show main.cf default setting */
#define SHOW_NAME (1<<2) /* show main.cf parameter name */
#define HIDE_NAME (1<<2) /* hide main.cf parameter name */
#define SHOW_MAPS (1<<3) /* show map types */
#define EDIT_MAIN (1<<4) /* edit main.cf */
#define EDIT_CONF (1<<4) /* edit main.cf or master.cf */
#define SHOW_LOCKS (1<<5) /* show mailbox lock methods */
#define SHOW_EVAL (1<<6) /* expand main.cf right-hand sides */
#define SHOW_SASL_SERV (1<<7) /* show server auth plugin types */
#define SHOW_SASL_CLNT (1<<8) /* show client auth plugin types */
#define COMMENT_OUT (1<<9) /* #-out selected main.cf entries */
#define SHOW_MASTER (1<<10) /* show master.cf entries */
#define MASTER_ENTRY (1<<10) /* manage master.cf entries */
#define FOLD_LINE (1<<11) /* fold long *.cf entries */
#define EDIT_EXCL (1<<12) /* exclude main.cf entries */
#define MASTER_FIELD (1<<13) /* hierarchical pathname */
#define MAIN_PARAM (1<<14) /* manage main.cf entries */
#define EXP_DSN_TEMPL (1<<15) /* expand bounce templates */
#define PARAM_CLASS (1<<16) /* select parameter class */
#define MAIN_OVER (1<<17) /* override parameter values */
#define DUMP_DSN_TEMPL (1<<18) /* show bounce templates */
#define MASTER_PARAM (1<<19) /* manage master.cf -o name=value */
#define DEF_MODE SHOW_NAME /* default mode */
#define DEF_MODE 0
/*
* Structure for one "valid parameter" (built-in, service-defined or valid
@ -105,7 +113,7 @@ extern VSTRING *param_string_buf;
* Structure of one master.cf entry.
*/
typedef struct {
char *name_space; /* service.type, parameter name space */
char *name_space; /* service/type, parameter name space */
ARGV *argv; /* null, or master.cf fields */
DICT *all_params; /* null, or all name=value entries */
HTABLE *valid_names; /* null, or "valid" parameter names */
@ -113,10 +121,31 @@ typedef struct {
#define PC_MASTER_MIN_FIELDS 8 /* mandatory field count */
/*
* Lookup table for master.cf entries. The table is terminated with an entry
* that has a null argv member.
*/
#define PC_MASTER_NAME_SERVICE "service"
#define PC_MASTER_NAME_TYPE "type"
#define PC_MASTER_NAME_PRIVATE "private"
#define PC_MASTER_NAME_UNPRIV "unprivileged"
#define PC_MASTER_NAME_CHROOT "chroot"
#define PC_MASTER_NAME_WAKEUP "wakeup"
#define PC_MASTER_NAME_MAXPROC "process_limit"
#define PC_MASTER_NAME_CMD "command"
#define PC_MASTER_FIELD_SERVICE 0 /* service name */
#define PC_MASTER_FIELD_TYPE 1 /* service type */
#define PC_MASTER_FIELD_PRIVATE 2 /* private service */
#define PC_MASTER_FIELD_UNPRIV 3 /* unprivileged service */
#define PC_MASTER_FIELD_CHROOT 4 /* chrooted service */
#define PC_MASTER_FIELD_WAKEUP 5 /* wakeup timer */
#define PC_MASTER_FIELD_MAXPROC 6 /* process limit */
#define PC_MASTER_FIELD_CMD 7 /* command */
#define PC_MASTER_FIELD_WILDC -1 /* wild-card */
#define PC_MASTER_FIELD_NONE -2 /* not available
*
/* Lookup table for master.cf
* entries. The table is terminated
* with an entry that has a null argv
* member. */
PC_MASTER_ENT *master_table;
/*
@ -147,18 +176,75 @@ extern void show_parameters(VSTREAM *, int, int, char **);
/*
* postconf_edit.c
*/
extern void edit_parameters(int, int, char **);
extern void edit_main(int, int, char **);
extern void edit_master(int, int, char **);
/*
* postconf_master.c.
*/
extern const char daemon_options_expecting_value[];
extern void read_master(int);
extern void show_master(VSTREAM *, int, char **);
extern void show_master_entries(VSTREAM *, int, int, char **);
extern const char *parse_master_entry(PC_MASTER_ENT *, const char *);
extern void print_master_entry(VSTREAM *, int, PC_MASTER_ENT *);
extern void free_master_entry(PC_MASTER_ENT *);
extern void show_master_fields(VSTREAM *, int, int, char **);
extern void edit_master_field(PC_MASTER_ENT *, int, const char *);
extern void show_master_params(VSTREAM *, int, int, char **);
extern void edit_master_param(PC_MASTER_ENT *, int, const char *, const char *);
#define WARN_ON_OPEN_ERROR 0
#define FAIL_ON_OPEN_ERROR 1
#define PC_MASTER_BLANKS " \t\r\n" /* XXX */
/*
* Master.cf parameter namespace management. The idea is to manage master.cf
* "-o name=value" settings with other tools than text editors.
*
* The natural choice is to use "service-name.service-type.parameter-name", but
* unfortunately the '.' may appear in service and parameter names.
*
* For example, a spawn(8) listener can have a service name 127.0.0.1:10028.
* This service name becomes part of a service-dependent parameter name
* "127.0.0.1:10028_time_limit". All those '.' characters mean we can't use
* '.' as the parameter namespace delimiter.
*
* (We could require that such service names are specified as $foo:port with
* the value of "foo" defined in main.cf or at the top of master.cf.)
*
* But it is easier if we use '/' instead.
*/
#define PC_NAMESP_SEP_CH '/'
#define PC_NAMESP_SEP_STR "/"
#define PC_LEGACY_SEP_CH '.'
/*
* postconf_match.c.
*/
#define PC_MATCH_WILDC_STR "*"
#define PC_MATCH_ANY(p) ((p)[0] == PC_MATCH_WILDC_STR[0] && (p)[1] == 0)
#define PC_MATCH_STRING(p, s) (PC_MATCH_ANY(p) || strcmp((p), (s)) == 0)
extern ARGV *parse_service_pattern(const char *, int, int);
extern int parse_field_pattern(const char *);
#define IS_MAGIC_SERVICE_PATTERN(pat) \
(PC_MATCH_ANY((pat)->argv[0]) || PC_MATCH_ANY((pat)->argv[1]))
#define MATCH_SERVICE_PATTERN(pat, name, type) \
(PC_MATCH_STRING((pat)->argv[0], (name)) \
&& PC_MATCH_STRING((pat)->argv[1], (type)))
#define is_magic_field_pattern(pat) ((pat) == PC_MASTER_FIELD_WILDC)
#define str_field_pattern(pat) ((const char *) (field_name_offset[pat].name))
#define IS_MAGIC_PARAM_PATTERN(pat) PC_MATCH_ANY(pat)
#define MATCH_PARAM_PATTERN(pat, name) PC_MATCH_STRING((pat), (name))
/* The following is not part of the postconf_match API. */
extern NAME_CODE field_name_offset[];
/*
* postconf_builtin.c.
*/
@ -197,6 +283,11 @@ const char *lookup_parameter_value(int, const char *, PC_MASTER_ENT *,
char *expand_parameter_value(VSTRING *, int, const char *, PC_MASTER_ENT *);
/*
* postconf_print.c.
*/
extern void print_line(VSTREAM *, int, const char *,...);
/*
* postconf_unused.c.
*/

View File

@ -2,24 +2,57 @@
/* NAME
/* postconf_edit 3
/* SUMMARY
/* edit main.cf
/* edit main.cf or master.cf
/* SYNOPSIS
/* #include <postconf.h>
/*
/* void edit_parameters(mode, argc, argv)
/* void edit_main(mode, argc, argv)
/* int mode;
/* int argc;
/* char **argv;
/*
/* void edit_master(mode, argc, argv)
/* int mode;
/* int argc;
/* char **argv;
/* DESCRIPTION
/* Edit the \fBmain.cf\fR configuration file, and update
/* parameter settings with the "\fIname\fR=\fIvalue\fR" pairs
/* given on the command line. The file is copied to a temporary
/* file then renamed into place.
/* edit_main() edits the \fBmain.cf\fR configuration
/* file. It replaces or adds parameter settings given as
/* "\fIname=value\fR" pairs given on the command line, or
/* removes parameter settings given as "\fIname\fR" on the
/* command line. The file is copied to a temporary file
/* then renamed into place.
/*
/* edit_master() edits the \fBmaster.cf\fR configuration file.
/* The file is copied to a temporary file then renamed into
/* place. Depending on the flags in \fBmode\fR:
/* .IP MASTER_ENTRY
/* With EDIT_CONF, edit_master() replaces or adds entire
/* master.cf entries, specified on the command line as
/* "\fIname/type = name type private unprivileged chroot wakeup
/* process_limit command...\fR".
/*
/* With EDIT_EXCL or COMMENT_OUT, edit_master() removes or
/* comments out entries specified on the command line as
/* "\fIname/type\fR.
/* .IP MASTER_FIELD
/* With EDIT_CONF, edit_master() replaces the value of specific
/* service attributes, specified on the command line as
/* "\fIname/type/attribute = value\fR".
/* .IP MASTER_PARAM
/* With EDIT_CONF, edit_master() replaces or adds the value
/* of service parameters, specified on the command line as
/* "\fIname/type/parameter = value\fR".
/*
/* With EDIT_EXCL, edit_master() removes service parameters
/* specified on the command line as "\fIparametername\fR".
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* FILES
/* /etc/postfix/main.cf, Postfix configuration parameters
/* /etc/postfix/main.cf.tmp, temporary name
/* /etc/postfix/master.cf, Postfix configuration parameters
/* /etc/postfix/master.cf.tmp, temporary name
/* LICENSE
/* .ad
/* .fi
@ -47,6 +80,7 @@
#include <edit_file.h>
#include <readlline.h>
#include <stringops.h>
#include <split_at.h>
/* Global library. */
@ -58,9 +92,61 @@
#define STR(x) vstring_str(x)
/* edit_parameters - edit parameter file */
/* find_cf_info - pass-through non-content line, return content or null */
void edit_parameters(int mode, int argc, char **argv)
static char *find_cf_info(VSTRING *buf, VSTREAM *dst)
{
char *cp;
for (cp = STR(buf); ISSPACE(*cp) /* including newline */ ; cp++)
/* void */ ;
/* Pass-through comment, all-whitespace, or empty line. */
if (*cp == '#' || *cp == 0) {
vstream_fputs(STR(buf), dst);
return (0);
} else {
return (cp);
}
}
/* next_cf_line - return next content line, pass-through non-content */
static char *next_cf_line(VSTRING *buf, VSTREAM *src, VSTREAM *dst, int *lineno)
{
char *cp;
while (vstring_get(buf, src) != VSTREAM_EOF) {
if (lineno)
*lineno += 1;
if ((cp = find_cf_info(buf, dst)) != 0)
return (cp);
}
return (0);
}
/* gobble_cf_line - accumulate multi-line content, pass-through non-content */
static void gobble_cf_line(VSTRING *full_entry_buf, VSTRING *line_buf,
VSTREAM *src, VSTREAM *dst, int *lineno)
{
int ch;
vstring_strcpy(full_entry_buf, STR(line_buf));
for (;;) {
if ((ch = VSTREAM_GETC(src)) != VSTREAM_EOF)
vstream_ungetc(src, ch);
if ((ch != '#' && !ISSPACE(ch))
|| vstring_get(line_buf, src) == VSTREAM_EOF)
break;
lineno += 1;
if (find_cf_info(line_buf, dst))
vstring_strcat(full_entry_buf, STR(line_buf));
}
}
/* edit_main - edit main.cf file */
void edit_main(int mode, int argc, char **argv)
{
char *path;
EDIT_FILE *ep;
@ -69,8 +155,8 @@ void edit_parameters(int mode, int argc, char **argv)
VSTRING *buf = vstring_alloc(100);
VSTRING *key = vstring_alloc(10);
char *cp;
char *edit_key;
char *edit_val;
char *pattern;
char *edit_value;
HTABLE *table;
struct cvalue {
char *value;
@ -93,24 +179,24 @@ void edit_parameters(int mode, int argc, char **argv)
cp++;
if (*cp == '#')
msg_fatal("-e, -X, or -# accepts no comment input");
if (mode & EDIT_MAIN) {
if ((err = split_nameval(cp, &edit_key, &edit_val)) != 0)
if (mode & EDIT_CONF) {
if ((err = split_nameval(cp, &pattern, &edit_value)) != 0)
msg_fatal("%s: \"%s\"", err, cp);
} else if (mode & (COMMENT_OUT | EDIT_EXCL)) {
if (*cp == 0)
msg_fatal("-X or -# requires non-blank parameter names");
if (strchr(cp, '=') != 0)
msg_fatal("-X or -# requires parameter names only");
edit_key = cp;
trimblanks(edit_key, 0);
edit_val = 0;
msg_fatal("-X or -# requires parameter names without value");
pattern = cp;
trimblanks(pattern, 0);
edit_value = 0;
} else {
msg_panic("edit_parameters: unknown mode %d", mode);
msg_panic("edit_main: unknown mode %d", mode);
}
cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue));
cvalue->value = edit_val;
cvalue->value = edit_value;
cvalue->found = 0;
htable_enter(table, edit_key, (char *) cvalue);
htable_enter(table, pattern, (char *) cvalue);
}
/*
@ -139,15 +225,9 @@ void edit_parameters(int mode, int argc, char **argv)
#define STR(x) vstring_str(x)
interesting = 0;
while (vstring_get(buf, src) != VSTREAM_EOF) {
for (cp = STR(buf); ISSPACE(*cp) /* including newline */ ; cp++)
/* void */ ;
/* Copy comment, all-whitespace, or empty line. */
if (*cp == '#' || *cp == 0) {
vstream_fputs(STR(buf), dst);
}
while ((cp = next_cf_line(buf, src, dst, (int *) 0)) != 0) {
/* Copy, skip or replace continued text. */
else if (cp > STR(buf)) {
if (cp > STR(buf)) {
if (interesting == 0)
vstream_fputs(STR(buf), dst);
else if (mode & COMMENT_OUT)
@ -160,7 +240,7 @@ void edit_parameters(int mode, int argc, char **argv)
if ((interesting = !!cvalue) != 0) {
if (cvalue->found++ == 1)
msg_warn("%s: multiple entries for \"%s\"", path, STR(key));
if (mode & EDIT_MAIN)
if (mode & EDIT_CONF)
vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value);
else if (mode & COMMENT_OUT)
vstream_fprintf(dst, "#%s", cp);
@ -173,7 +253,7 @@ void edit_parameters(int mode, int argc, char **argv)
/*
* Generate new entries for parameters that were not found.
*/
if (mode & EDIT_MAIN) {
if (mode & EDIT_CONF) {
for (ht_info = ht = htable_list(table); *ht; ht++) {
cvalue = (struct cvalue *) ht[0]->value;
if (cvalue->found == 0)
@ -198,3 +278,298 @@ void edit_parameters(int mode, int argc, char **argv)
vstring_free(key);
htable_free(table, myfree);
}
/*
* Data structure to hold a master.cf edit request.
*/
typedef struct {
int match_count; /* hit count */
const char *raw_text; /* unparsed command-line argument */
char *parsed_text; /* destructive parse */
ARGV *service_pattern; /* service name, type, ... */
int field_number; /* attribute field number */
const char *param_pattern; /* parameter name */
char *edit_value; /* value substring */
} PC_MASTER_EDIT_REQ;
/* edit_master - edit master.cf file */
void edit_master(int mode, int argc, char **argv)
{
const char *myname = "edit_master";
char *path;
EDIT_FILE *ep;
VSTREAM *src;
VSTREAM *dst;
VSTRING *line_buf = vstring_alloc(100);
VSTRING *parse_buf = vstring_alloc(100);
int lineno;
PC_MASTER_ENT *new_entry;
VSTRING *full_entry_buf = vstring_alloc(100);
char *cp;
char *pattern;
int service_name_type_matched;
const char *err;
PC_MASTER_EDIT_REQ *edit_reqs;
PC_MASTER_EDIT_REQ *req;
int num_reqs = argc;
const char *edit_opts = "-Me, -Fe, -Pe, -X, or -#";
char *service_name;
char *service_type;
/*
* Sanity check.
*/
if (num_reqs <= 0)
msg_panic("%s: empty argument list", myname);
/*
* Preprocessing: split pattern=value, then split the pattern components.
*/
edit_reqs = (PC_MASTER_EDIT_REQ *) mymalloc(sizeof(*edit_reqs) * num_reqs);
for (req = edit_reqs; *argv != 0; req++, argv++) {
req->match_count = 0;
req->raw_text = *argv;
cp = req->parsed_text = mystrdup(req->raw_text);
if (strchr(cp, '\n') != 0)
msg_fatal("%s accept no multi-line input", edit_opts);
while (ISSPACE(*cp))
cp++;
if (*cp == '#')
msg_fatal("%s accept no comment input", edit_opts);
/* Separate the pattern from the value. */
if (mode & EDIT_CONF) {
if ((err = split_nameval(cp, &pattern, &req->edit_value)) != 0)
msg_fatal("%s: \"%s\"", err, req->raw_text);
if ((mode & MASTER_PARAM)
&& req->edit_value[strcspn(req->edit_value, PC_MASTER_BLANKS)])
msg_fatal("whitespace in parameter value: \"%s\"",
req->raw_text);
} else if (mode & (COMMENT_OUT | EDIT_EXCL)) {
if (strchr(cp, '=') != 0)
msg_fatal("-X or -# requires names without value");
pattern = cp;
trimblanks(pattern, 0);
req->edit_value = 0;
} else {
msg_panic("%s: unknown mode %d", myname, mode);
}
#define PC_MASTER_MASK (MASTER_ENTRY | MASTER_FIELD | MASTER_PARAM)
/*
* Split name/type or name/type/whatever pattern into components.
*/
switch (mode & PC_MASTER_MASK) {
case MASTER_ENTRY:
if ((req->service_pattern =
parse_service_pattern(pattern, 2, 2)) == 0)
msg_fatal("-Me, -MX or -M# requires service_name/type");
break;
case MASTER_FIELD:
if ((req->service_pattern =
parse_service_pattern(pattern, 3, 3)) == 0)
msg_fatal("-Fe or -FX requires service_name/type/field_name");
req->field_number =
parse_field_pattern(req->service_pattern->argv[2]);
if (is_magic_field_pattern(req->field_number))
msg_fatal("-Fe does not accept wild-card field name");
if ((mode & EDIT_CONF)
&& req->field_number < PC_MASTER_FIELD_CMD
&& req->edit_value[strcspn(req->edit_value, PC_MASTER_BLANKS)])
msg_fatal("-Fe does not accept whitespace in non-command field");
break;
case MASTER_PARAM:
if ((req->service_pattern =
parse_service_pattern(pattern, 3, 3)) == 0)
msg_fatal("-Pe or -PX requires service_name/type/parameter");
req->param_pattern = req->service_pattern->argv[2];
if (IS_MAGIC_PARAM_PATTERN(req->param_pattern))
msg_fatal("-Pe does not accept wild-card parameter name");
if ((mode & EDIT_CONF)
&& req->edit_value[strcspn(req->edit_value, PC_MASTER_BLANKS)])
msg_fatal("-Pe does not accept whitespace in parameter value");
break;
default:
msg_panic("%s: unknown edit mode %d", myname, mode);
}
}
/*
* Open a temp file for the result. This uses a deterministic name so we
* don't leave behind thrash with random names.
*/
set_config_dir();
path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0)
msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX);
dst = ep->tmp_fp;
/*
* Open the original file for input.
*/
if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0) {
/* OK to delete, since we control the temp file name exclusively. */
(void) unlink(ep->tmp_path);
msg_fatal("open %s for reading: %m", path);
}
/*
* Copy original file to temp file, while replacing service entries on
* the fly.
*/
service_name_type_matched = 0;
new_entry = 0;
lineno = 0;
while ((cp = next_cf_line(parse_buf, src, dst, &lineno)) != 0) {
vstring_strcpy(line_buf, STR(parse_buf));
/*
* Copy, skip or replace continued text.
*/
if (cp > STR(parse_buf)) {
if (service_name_type_matched == 0)
vstream_fputs(STR(line_buf), dst);
else if (mode & COMMENT_OUT)
vstream_fprintf(dst, "#%s", STR(line_buf));
}
/*
* Copy or replace (start of) logical line.
*/
else {
service_name_type_matched = 0;
/*
* Parse out the service name and type.
*/
if ((service_name = mystrtok(&cp, PC_MASTER_BLANKS)) == 0
|| (service_type = mystrtok(&cp, PC_MASTER_BLANKS)) == 0)
msg_fatal("file %s: line %d: specify service name and type "
"on the same line", path, lineno);
if (strchr(service_name, '='))
msg_fatal("file %s: line %d: service name syntax \"%s\" is "
"unsupported with %s", path, lineno, service_name,
edit_opts);
if (service_type[strcspn(service_type, "=/")] != 0)
msg_fatal("file %s: line %d: "
"service type syntax \"%s\" is unsupported with %s",
path, lineno, service_type, edit_opts);
/*
* Match each service pattern.
*/
for (req = edit_reqs; req < edit_reqs + num_reqs; req++) {
if (MATCH_SERVICE_PATTERN(req->service_pattern, service_name,
service_type)) {
service_name_type_matched = 1; /* Sticky flag */
req->match_count += 1;
/*
* Generate replacement master.cf entries.
*/
if ((mode & EDIT_CONF)
|| ((mode & MASTER_PARAM) && (mode & EDIT_EXCL))) {
switch (mode & PC_MASTER_MASK) {
/*
* Replace master.cf entry field or parameter
* value.
*/
case MASTER_FIELD:
case MASTER_PARAM:
if (new_entry == 0) {
/* Gobble up any continuation lines. */
gobble_cf_line(full_entry_buf, line_buf, src,
dst, &lineno);
new_entry = (PC_MASTER_ENT *)
mymalloc(sizeof(*new_entry));
if ((err = parse_master_entry(new_entry,
STR(full_entry_buf))) != 0)
msg_fatal("file %s: line %d: %s",
path, lineno, err);
}
if (mode & MASTER_FIELD) {
edit_master_field(new_entry, req->field_number,
req->edit_value);
} else {
edit_master_param(new_entry, mode,
req->param_pattern,
req->edit_value);
}
break;
/*
* Replace entire master.cf entry.
*/
case MASTER_ENTRY:
if (new_entry != 0)
free_master_entry(new_entry);
new_entry = (PC_MASTER_ENT *)
mymalloc(sizeof(*new_entry));
if ((err = parse_master_entry(new_entry,
req->edit_value)) != 0)
msg_fatal("%s: \"%s\"", err, req->raw_text);
break;
default:
msg_panic("%s: unknown edit mode %d", myname, mode);
}
}
}
}
/*
* Pass through or replace the current input line.
*/
if (new_entry) {
print_master_entry(dst, FOLD_LINE, new_entry);
free_master_entry(new_entry);
new_entry = 0;
} else if (service_name_type_matched == 0) {
vstream_fputs(STR(line_buf), dst);
} else if (mode & COMMENT_OUT) {
vstream_fprintf(dst, "#%s", STR(line_buf));
}
}
}
/*
* Postprocessing: when editing entire service entries, generate new
* entries for services not found. Otherwise (editing fields or
* parameters), "service not found" is a fatal error.
*/
for (req = edit_reqs; req < edit_reqs + num_reqs; req++) {
if (req->match_count == 0) {
if ((mode & MASTER_ENTRY) && (mode & EDIT_CONF)) {
new_entry = (PC_MASTER_ENT *) mymalloc(sizeof(*new_entry));
if ((err = parse_master_entry(new_entry, req->edit_value)) != 0)
msg_fatal("%s: \"%s\"", err, req->raw_text);
print_master_entry(dst, FOLD_LINE, new_entry);
free_master_entry(new_entry);
} else if ((mode & MASTER_ENTRY) == 0) {
msg_warn("unmatched service_name/type: \"%s\"", req->raw_text);
}
}
}
/*
* When all is well, rename the temp file to the original one.
*/
if (vstream_fclose(src))
msg_fatal("read %s: %m", path);
if (edit_file_close(ep) != 0)
msg_fatal("close %s%s: %m", path, EDIT_FILE_SUFFIX);
/*
* Cleanup.
*/
myfree(path);
vstring_free(line_buf);
vstring_free(parse_buf);
vstring_free(full_entry_buf);
for (req = edit_reqs; req < edit_reqs + num_reqs; req++) {
argv_free(req->service_pattern);
myfree(req->parsed_text);
}
myfree((char *) edit_reqs);
}

View File

@ -129,59 +129,6 @@ void set_parameters(char **name_val_array)
}
}
/* print_line - show line possibly folded, and with normalized whitespace */
static void print_line(VSTREAM *fp, int mode, const char *fmt,...)
{
va_list ap;
static VSTRING *buf = 0;
char *start;
char *next;
int line_len = 0;
int word_len;
/*
* One-off initialization.
*/
if (buf == 0)
buf = vstring_alloc(100);
/*
* Format the text.
*/
va_start(ap, fmt);
vstring_vsprintf(buf, fmt, ap);
va_end(ap);
/*
* Normalize the whitespace. We don't use the line_wrap() routine because
* 1) that function does not normalize whitespace between words and 2) we
* want to normalize whitespace even when not wrapping lines.
*
* XXX Some parameters preserve whitespace: for example, smtpd_banner and
* smtpd_reject_footer. If we have to preserve whitespace between words,
* then perhaps readlline() can be changed to canonicalize whitespace
* that follows a newline.
*/
for (start = STR(buf); *(start += strspn(start, SEPARATORS)) != 0; start = next) {
word_len = strcspn(start, SEPARATORS);
if (*(next = start + word_len) != 0)
*next++ = 0;
if (word_len > 0 && line_len > 0) {
if ((mode & FOLD_LINE) == 0 || line_len + word_len < LINE_LIMIT) {
vstream_fputs(" ", fp);
line_len += 1;
} else {
vstream_fputs("\n" INDENT_TEXT, fp);
line_len = INDENT_LEN;
}
}
vstream_fputs(start, fp);
line_len += word_len;
}
vstream_fputs("\n", fp);
}
/* print_parameter - show specific parameter */
static void print_parameter(VSTREAM *fp, int mode, const char *name,
@ -202,7 +149,7 @@ static void print_parameter(VSTREAM *fp, int mode, const char *name,
if ((mode & SHOW_EVAL) != 0 && PC_RAW_PARAMETER(node) == 0)
value = expand_parameter_value((VSTRING *) 0, mode, value,
(PC_MASTER_ENT *) 0);
if (mode & SHOW_NAME) {
if ((mode & HIDE_NAME) == 0) {
print_line(fp, mode, "%s = %s\n", name, value);
} else {
print_line(fp, mode, "%s\n", value);

View File

@ -11,19 +11,76 @@
/* void read_master(fail_on_open)
/* int fail_on_open;
/*
/* void show_master(fp, mode, filters)
/* void show_master_entries(fp, mode, service_filters)
/* VSTREAM *fp;
/* int mode;
/* char **filters;
/* char **service_filters;
/*
/* void show_master_fields(fp, mode, n_filters, field_filters)
/* VSTREAM *fp;
/* int mode;
/* int n_filters;
/* char **field_filters;
/*
/* void edit_master_field(masterp, field, new_value)
/* PC_MASTER_ENT *masterp;
/* int field;
/* const char *new_value;
/*
/* void show_master_params(fp, mode, argc, **param_filters)
/* VSTREAM *fp;
/* int mode;
/* int argc;
/* char **param_filters;
/*
/* void edit_master_param(masterp, mode, param_name, param_value)
/* PC_MASTER_ENT *masterp;
/* int mode;
/* const char *param_name;
/* const char *param_value;
/* AUXILIARY FUNCTIONS
/* const char *parse_master_entry(masterp, buf)
/* PC_MASTER_ENT *masterp;
/* const char *buf;
/*
/* void print_master_entry(fp, mode, masterp)
/* VSTREAM *fp;
/* int mode;
/* PC_MASTER_ENT *masterp;
/*
/* void free_master_entry(masterp)
/* PC_MASTER_ENT *masterp;
/* DESCRIPTION
/* read_master() reads entries from master.cf into memory.
/*
/* show_master() writes the entries in the master.cf file
/* show_master_entries() writes the entries in the master.cf
/* file to the specified stream.
/*
/* show_master_fields() writes name/type/field=value records to
/* the specified stream.
/*
/* edit_master_field() updates the value of a single-column
/* or multi-column attribute.
/*
/* show_master_params() writes name/type/parameter=value records
/* to the specified stream.
/*
/* edit_master_param() updates, removes or adds the named
/* parameter in a master.cf entry (the remove request ignores
/* the parameter value).
/*
/* daemon_options_expecting_value[] is an array of master.cf
/* daemon command-line options that expect an option value.
/*
/* parse_master_entry() parses a (perhaps multi-line) string
/* that contains a complete master.cf entry, and normalizes
/* daemon command-line options to simplify further handling.
/*
/* print_master_entry() prints a parsed master.cf entry.
/*
/* free_master_entry() returns storage to the heap that was
/* allocated by parse_master_entry().
/*
/* Arguments
/* .IP fail_on_open
/* Specify FAIL_ON_OPEN if open failure is a fatal error,
@ -31,12 +88,37 @@
/* .IP fp
/* Output stream.
/* .IP mode
/* If the FOLD_LINE flag is set, show_master() wraps long
/* output lines.
/* .IP filters
/* A list of zero or more expressions in master_service(3)
/* format. If no list is specified, show_master() outputs
/* Bit-wise OR of flags. Flags other than the following are ignored.
/* .RS
/* .IP FOLD_LINE
/* Wrap long output lines.
/* .IP SHOW_EVAL
/* Expand $name in parameter values.
/* .IP EDIT_EXCL
/* Request that edit_master_param() removes the parameter.
/* .RE
/* .IP n_filters
/* The number of command-line filters.
/* .IP field_filters
/* A list of zero or more service field patterns (name/type/field).
/* The output is formatted as "name/type/field = value". If
/* no filters are specified, show_master_fields() outputs the
/* fields of all master.cf entries in the specified order.
/* .IP param_filters
/* A list of zero or more service parameter patterns
/* (name/type/parameter). The output is formatted as
/* "name/type/parameter = value". If no filters are specified,
/* show_master_params() outputs the parameters of all master.cf
/* entries in sorted order.
/* .IP service_filters
/* A list of zero or more service patterns (name or name/type).
/* If no filters are specified, show_master_entries() outputs
/* all master.cf entries in the specified order.
/* .IP field
/* Index into parsed master.cf entry.
/* .IP new_value
/* Replacement value for the specified field. It is split
/* in whitespace in case of a multi-field attribute.
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* LICENSE
@ -54,6 +136,8 @@
#include <sys_defs.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
/* Utility library. */
@ -64,11 +148,15 @@
#include <vstream.h>
#include <readlline.h>
#include <stringops.h>
#include <split_at.h>
/* Global library. */
#include <mail_params.h>
#include <match_service.h>
/* Master library. */
#include <master_proto.h>
/* Application-specific. */
@ -76,6 +164,30 @@
const char daemon_options_expecting_value[] = "o";
/*
* Data structure to capture a command-line service field filter.
*/
typedef struct {
int match_count; /* hit count */
const char *raw_text; /* full pattern text */
ARGV *service_pattern; /* parsed service name, type, ... */
int field_pattern; /* parsed field pattern */
const char *param_pattern; /* parameter pattern */
} PC_MASTER_FIELD_REQ;
/*
* Valid inputs.
*/
static const char *valid_master_types[] = {
MASTER_XPORT_NAME_UNIX,
MASTER_XPORT_NAME_FIFO,
MASTER_XPORT_NAME_INET,
MASTER_XPORT_NAME_PASS,
0,
};
static const char valid_bool_types[] = "yn-";
#define STR(x) vstring_str(x)
/* normalize_options - bring options into canonical form */
@ -97,7 +209,7 @@ static void normalize_options(ARGV *argv)
for (cp = arg + 1; *cp; cp++) {
if (strchr(daemon_options_expecting_value, *cp) != 0
&& cp > arg + 1) {
/* Split "-stuffo" into "-stuff" and "-o". */
/* Split "-stuffozz" into "-stuff" and "-ozz". */
junk = concatenate("-", cp, (char *) 0);
argv_insert_one(argv, field + 1, junk);
myfree(junk);
@ -120,9 +232,80 @@ static void normalize_options(ARGV *argv)
}
}
/* parse_master_line - parse one master line */
/* fix_fatal - fix multiline text before release */
static const char *parse_master_line(PC_MASTER_ENT *masterp, const char *buf)
static NORETURN PRINTFLIKE(1, 2) fix_fatal(const char *fmt,...)
{
VSTRING *buf = vstring_alloc(100);
va_list ap;
/*
* Replace newline with whitespace.
*/
va_start(ap, fmt);
vstring_vsprintf(buf, fmt, ap);
va_end(ap);
translit(STR(buf), "\n", " ");
msg_fatal("%s", STR(buf));
/* NOTREACHED */
}
/* check_master_entry - sanity check master.cf entry */
static void check_master_entry(ARGV *argv, const char *raw_text)
{
const char **cpp;
char *cp;
int len;
int field;
cp = argv->argv[PC_MASTER_FIELD_TYPE];
for (cpp = valid_master_types; /* see below */ ; cpp++) {
if (*cpp == 0)
fix_fatal("invalid " PC_MASTER_NAME_TYPE " field \"%s\" in \"%s\"",
cp, raw_text);
if (strcmp(*cpp, cp) == 0)
break;
}
for (field = PC_MASTER_FIELD_PRIVATE; field <= PC_MASTER_FIELD_CHROOT; field++) {
cp = argv->argv[field];
if (cp[1] != 0 || strchr(valid_bool_types, *cp) == 0)
fix_fatal("invalid %s field \%s\" in \"%s\"",
str_field_pattern(field), cp, raw_text);
}
cp = argv->argv[PC_MASTER_FIELD_WAKEUP];
len = strlen(cp);
if (len > 0 && cp[len - 1] == '?')
len--;
if (!(cp[0] == '-' && len == 1) && strspn(cp, "0123456789") != len)
fix_fatal("invalid " PC_MASTER_NAME_WAKEUP " field \%s\" in \"%s\"",
cp, raw_text);
cp = argv->argv[PC_MASTER_FIELD_MAXPROC];
if (strcmp("-", cp) != 0 && cp[strspn(cp, "0123456789")] != 0)
fix_fatal("invalid " PC_MASTER_NAME_MAXPROC " field \%s\" in \"%s\"",
cp, raw_text);
}
/* free_master_entry - destroy parsed entry */
void free_master_entry(PC_MASTER_ENT *masterp)
{
/* XX Fixme: allocation/deallocation asymmetry. */
myfree(masterp->name_space);
argv_free(masterp->argv);
if (masterp->valid_names)
htable_free(masterp->valid_names, myfree);
if (masterp->all_params)
dict_free(masterp->all_params);
myfree((char *) masterp);
}
/* parse_master_entry - parse one master line */
const char *parse_master_entry(PC_MASTER_ENT *masterp, const char *buf)
{
ARGV *argv;
@ -134,17 +317,18 @@ static const char *parse_master_line(PC_MASTER_ENT *masterp, const char *buf)
* The postconf command needs to show default fields as "-", and needs to
* know about all service names so that it can generate service-dependent
* parameter names (transport-dependent etc.).
*
* XXX Do per-field sanity checks.
*/
#define MASTER_BLANKS " \t\r\n" /* XXX */
argv = argv_split(buf, MASTER_BLANKS);
argv = argv_split(buf, PC_MASTER_BLANKS);
if (argv->argc < PC_MASTER_MIN_FIELDS) {
argv_free(argv); /* Coverity 201311 */
return ("bad field count");
}
check_master_entry(argv, buf);
normalize_options(argv);
masterp->name_space =
concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0);
concatenate(argv->argv[0], PC_NAMESP_SEP_STR, argv->argv[1], (char *) 0);
masterp->argv = argv;
masterp->valid_names = 0;
masterp->all_params = 0;
@ -194,8 +378,8 @@ void read_master(int fail_on_open_error)
while (readlline(buf, fp, &line_count) != 0) {
master_table = (PC_MASTER_ENT *) myrealloc((char *) master_table,
(entry_count + 2) * sizeof(*master_table));
if ((err = parse_master_line(master_table + entry_count,
STR(buf))) != 0)
if ((err = parse_master_entry(master_table + entry_count,
STR(buf))) != 0)
msg_fatal("file %s: line %d: %s", path, line_count, err);
entry_count += 1;
}
@ -210,9 +394,9 @@ void read_master(int fail_on_open_error)
myfree(path);
}
/* print_master_line - print one master line */
/* print_master_entry - print one master line */
static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
void print_master_entry(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
{
char **argv = masterp->argv->argv;
const char *arg;
@ -268,11 +452,11 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
*/
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
in_daemon_options = 0;
if ((mode & FOLD_LINE)
&& line_len > column_goal[PC_MASTER_MIN_FIELDS - 1]) {
#if 0
if (mode & FOLD_LINE)
/* Force line wrap. */
line_len = LINE_LIMIT;
}
#endif
}
/*
@ -281,6 +465,9 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
else if (strchr(daemon_options_expecting_value, arg[1]) != 0
&& (aval = argv[field + 1]) != 0) {
/* Force line wrap before option with value. */
line_len = LINE_LIMIT;
/*
* Optionally, expand $name in parameter value.
*/
@ -313,36 +500,497 @@ static void print_master_line(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
ADD_SPACE;
ADD_TEXT(aval, strlen(aval));
field += 1;
/* Force line wrap after option with value. */
line_len = LINE_LIMIT;
}
}
vstream_fputs("\n", fp);
if (msg_verbose)
vstream_fflush(fp);
}
/* show_master - show master.cf entries */
/* show_master_entries - show master.cf entries */
void show_master(VSTREAM *fp, int mode, char **filters)
void show_master_entries(VSTREAM *fp, int mode, int argc, char **argv)
{
PC_MASTER_ENT *masterp;
ARGV *service_filter = 0;
PC_MASTER_FIELD_REQ *field_reqs;
PC_MASTER_FIELD_REQ *req;
/*
* Initialize the service filter.
* Parse the filter expressions.
*/
if (filters[0])
service_filter = match_service_init_argv(filters);
if (argc > 0) {
field_reqs = (PC_MASTER_FIELD_REQ *)
mymalloc(sizeof(*field_reqs) * argc);
for (req = field_reqs; req < field_reqs + argc; req++) {
req->match_count = 0;
req->raw_text = *argv++;
req->service_pattern =
parse_service_pattern(req->raw_text, 1, 2);
if (req->service_pattern == 0)
msg_fatal("-M option requires service_name[/type]");
}
}
/*
* Iterate over the master table.
*/
for (masterp = master_table; masterp->argv != 0; masterp++)
if ((service_filter == 0
|| match_service_match(service_filter, masterp->name_space))
&& ((mode & SHOW_NONDEF) == 0 || masterp->all_params != 0))
print_master_line(fp, mode, masterp);
for (masterp = master_table; masterp->argv != 0; masterp++) {
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (MATCH_SERVICE_PATTERN(req->service_pattern,
masterp->argv->argv[0],
masterp->argv->argv[1])) {
req->match_count++;
print_master_entry(fp, mode, masterp);
}
}
} else {
print_master_entry(fp, mode, masterp);
}
}
/*
* Cleanup.
*/
if (service_filter != 0)
argv_free(service_filter);
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (req->match_count == 0)
msg_warn("unmatched request: \"%s\"", req->raw_text);
argv_free(req->service_pattern);
}
myfree((char *) field_reqs);
}
}
/* print_master_field - scaffolding */
static void print_master_field(VSTREAM *fp, int mode,
PC_MASTER_ENT *masterp,
int field)
{
char **argv = masterp->argv->argv;
const char *arg;
const char *aval;
int arg_len;
int line_len;
int in_daemon_options;
/*
* Show the field value, or the first value in the case of a multi-column
* field.
*/
#define ADD_CHAR(ch) ADD_TEXT((ch), 1)
line_len = 0;
if ((mode & HIDE_NAME) == 0) {
ADD_TEXT(argv[0], strlen(argv[0]));
ADD_CHAR(PC_NAMESP_SEP_STR);
ADD_TEXT(argv[1], strlen(argv[1]));
ADD_CHAR(PC_NAMESP_SEP_STR);
ADD_TEXT(str_field_pattern(field), strlen(str_field_pattern(field)));
ADD_TEXT(" = ", 3);
if (line_len + strlen(argv[field]) > LINE_LIMIT) {
vstream_fputs("\n" INDENT_TEXT, fp);
line_len = INDENT_LEN;
}
}
ADD_TEXT(argv[field], strlen(argv[field]));
/*
* Format the daemon command-line options and non-option arguments. Here,
* we have no data-dependent preference for column positions, but we do
* have argument grouping preferences.
*/
if (field == PC_MASTER_FIELD_CMD) {
in_daemon_options = 1;
for (field += 1; (arg = argv[field]) != 0; field++) {
arg_len = strlen(arg);
aval = 0;
if (in_daemon_options) {
/*
* We make no special case for generic options (-v -D)
* options.
*/
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
in_daemon_options = 0;
} else if (strchr(daemon_options_expecting_value, arg[1]) != 0
&& (aval = argv[field + 1]) != 0) {
/* Force line break before option with value. */
line_len = LINE_LIMIT;
/*
* Optionally, expand $name in parameter value.
*/
if (strcmp(arg, "-o") == 0
&& (mode & SHOW_EVAL) != 0)
aval = expand_parameter_value((VSTRING *) 0, mode,
aval, masterp);
/*
* Keep option and value on the same line.
*/
arg_len += strlen(aval) + 1;
}
}
/*
* Insert a line break when the next item won't fit.
*/
if (line_len > INDENT_LEN) {
if ((mode & FOLD_LINE) == 0
|| line_len + 1 + arg_len < LINE_LIMIT) {
ADD_SPACE;
} else {
vstream_fputs("\n" INDENT_TEXT, fp);
line_len = INDENT_LEN;
}
}
ADD_TEXT(arg, strlen(arg));
if (aval) {
ADD_SPACE;
ADD_TEXT(aval, strlen(aval));
field += 1;
/* Force line break after option with value. */
line_len = LINE_LIMIT;
}
}
}
vstream_fputs("\n", fp);
if (msg_verbose)
vstream_fflush(fp);
}
/* show_master_fields - show master.cf fields */
void show_master_fields(VSTREAM *fp, int mode, int argc, char **argv)
{
const char *myname = "show_master_fields";
PC_MASTER_ENT *masterp;
PC_MASTER_FIELD_REQ *field_reqs;
PC_MASTER_FIELD_REQ *req;
int field;
/*
* Parse the filter expressions.
*/
if (argc > 0) {
field_reqs = (PC_MASTER_FIELD_REQ *)
mymalloc(sizeof(*field_reqs) * argc);
for (req = field_reqs; req < field_reqs + argc; req++) {
req->match_count = 0;
req->raw_text = *argv++;
req->service_pattern =
parse_service_pattern(req->raw_text, 1, 3);
if (req->service_pattern == 0)
msg_fatal("-F option requires service_name[/type[/field]]");
field = req->field_pattern =
parse_field_pattern(req->service_pattern->argv[2]);
if (is_magic_field_pattern(field) == 0
&& (field < 0 || field > PC_MASTER_FIELD_CMD))
msg_panic("%s: bad attribute field index: %d",
myname, field);
}
}
/*
* Iterate over the master table.
*/
for (masterp = master_table; masterp->argv != 0; masterp++) {
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (MATCH_SERVICE_PATTERN(req->service_pattern,
masterp->argv->argv[0],
masterp->argv->argv[1])) {
req->match_count++;
field = req->field_pattern;
if (is_magic_field_pattern(field)) {
for (field = 0; field <= PC_MASTER_FIELD_CMD; field++)
print_master_field(fp, mode, masterp, field);
} else {
print_master_field(fp, mode, masterp, field);
}
}
}
} else {
for (field = 0; field <= PC_MASTER_FIELD_CMD; field++)
print_master_field(fp, mode, masterp, field);
}
}
/*
* Cleanup.
*/
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (req->match_count == 0)
msg_warn("unmatched request: \"%s\"", req->raw_text);
argv_free(req->service_pattern);
}
myfree((char *) field_reqs);
}
}
/* edit_master_field - replace master.cf field value. */
void edit_master_field(PC_MASTER_ENT *masterp, int field,
const char *new_value)
{
/*
* Replace multi-column attribute.
*/
if (field == PC_MASTER_FIELD_CMD) {
argv_truncate(masterp->argv, PC_MASTER_FIELD_CMD);
argv_split_append(masterp->argv, new_value, PC_MASTER_BLANKS);
}
/*
* Replace single-column attribute.
*/
else {
argv_replace_one(masterp->argv, field, new_value);
}
/*
* Do per-field sanity checks.
*/
check_master_entry(masterp->argv, new_value);
}
/* print_master_param - scaffolding */
static void print_master_param(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp,
const char *param_name, const char *param_value)
{
if ((mode & SHOW_EVAL) != 0)
param_value = expand_parameter_value((VSTRING *) 0, mode,
param_value, masterp);
if ((mode & HIDE_NAME) == 0) {
print_line(fp, mode, "%s%c%s = %s\n",
masterp->name_space, PC_NAMESP_SEP_CH,
param_name, param_value);
} else {
print_line(fp, mode, "%s\n", param_value);
}
if (msg_verbose)
vstream_fflush(fp);
}
/* sort_argv_cb - sort argv call-back */
static int sort_argv_cb(const void *a, const void *b)
{
return (strcmp(*(char **) a, *(char **) b));
}
/* show_master_any_param - show any parameter in master.cf service entry */
static void show_master_any_param(VSTREAM *fp, int mode, PC_MASTER_ENT *masterp)
{
const char *myname = "show_master_any_param";
ARGV *argv = argv_alloc(10);
DICT *dict = masterp->all_params;
const char *param_name;
const char *param_value;
int param_count = 0;
int how;
char **cpp;
/*
* Print parameters in sorted order. The number of parameters per
* master.cf entry is small, so we optmiize for code simplicity and don't
* worry about the cost of double lookup.
*/
/* Look up the parameter names and ignore the values. */
for (how = DICT_SEQ_FUN_FIRST;
dict->sequence(dict, how, &param_name, &param_value) == 0;
how = DICT_SEQ_FUN_NEXT) {
argv_add(argv, param_name, ARGV_END);
param_count++;
}
/* Print the parameters in sorted order. */
qsort(argv->argv, param_count, sizeof(argv->argv[0]), sort_argv_cb);
for (cpp = argv->argv; (param_name = *cpp) != 0; cpp++) {
if ((param_value = dict_get(dict, param_name)) == 0)
msg_panic("%s: parameter name not found: %s", myname, param_name);
print_master_param(fp, mode, masterp, param_name, param_value);
}
/*
* Clean up.
*/
argv_free(argv);
}
/* show_master_params - show master.cf params */
void show_master_params(VSTREAM *fp, int mode, int argc, char **argv)
{
PC_MASTER_ENT *masterp;
PC_MASTER_FIELD_REQ *field_reqs;
PC_MASTER_FIELD_REQ *req;
DICT *dict;
const char *param_value;
/*
* Parse the filter expressions.
*/
if (argc > 0) {
field_reqs = (PC_MASTER_FIELD_REQ *)
mymalloc(sizeof(*field_reqs) * argc);
for (req = field_reqs; req < field_reqs + argc; req++) {
req->match_count = 0;
req->raw_text = *argv++;
req->service_pattern =
parse_service_pattern(req->raw_text, 1, 3);
if (req->service_pattern == 0)
msg_fatal("-P option requires service_name[/type[/parameter]]");
req->param_pattern = req->service_pattern->argv[2];
}
}
/*
* Iterate over the master table.
*/
for (masterp = master_table; masterp->argv != 0; masterp++) {
if ((dict = masterp->all_params) != 0) {
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (MATCH_SERVICE_PATTERN(req->service_pattern,
masterp->argv->argv[0],
masterp->argv->argv[1])) {
if (IS_MAGIC_PARAM_PATTERN(req->param_pattern)) {
show_master_any_param(fp, mode, masterp);
req->match_count += 1;
} else if ((param_value = dict_get(dict,
req->param_pattern)) != 0) {
print_master_param(fp, mode, masterp,
req->param_pattern,
param_value);
req->match_count += 1;
}
}
}
} else {
show_master_any_param(fp, mode, masterp);
}
}
}
/*
* Cleanup.
*/
if (argc > 0) {
for (req = field_reqs; req < field_reqs + argc; req++) {
if (req->match_count == 0)
msg_warn("unmatched request: \"%s\"", req->raw_text);
argv_free(req->service_pattern);
}
myfree((char *) field_reqs);
}
}
/* edit_master_param - update, add or remove -o parameter=value */
void edit_master_param(PC_MASTER_ENT *masterp, int mode,
const char *param_name,
const char *param_value)
{
const char *myname = "edit_master_param";
ARGV *argv = masterp->argv;
const char *arg;
const char *aval;
int param_match = 0;
int name_len = strlen(param_name);
int field;
for (field = PC_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
arg = argv->argv[field];
/*
* Stop at the first non-option argument or end-of-list.
*/
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
break;
}
/*
* Zoom in on command-line options with a value.
*/
else if (strchr(daemon_options_expecting_value, arg[1]) != 0
&& (aval = argv->argv[field + 1]) != 0) {
/*
* Zoom in on "-o parameter=value".
*/
if (strcmp(arg, "-o") == 0) {
if (strncmp(aval, param_name, name_len) == 0
&& aval[name_len] == '=') {
param_match = 1;
switch (mode & (EDIT_CONF | EDIT_EXCL)) {
/*
* Update parameter=value.
*/
case EDIT_CONF:
aval = concatenate(param_name, "=",
param_value, (char *) 0);
argv_replace_one(argv, field + 1, aval);
myfree((char *) aval);
if (masterp->all_params)
dict_put(masterp->all_params, param_name, param_value);
/* XXX Update parameter "used/defined" status. */
break;
/*
* Delete parameter=value.
*/
case EDIT_EXCL:
argv_delete(argv, field, 2);
if (masterp->all_params)
dict_del(masterp->all_params, param_name);
/* XXX Update parameter "used/defined" status. */
field -= 2;
break;
default:
msg_panic("%s: unexpected mode: %d", myname, mode);
}
}
}
/*
* Skip over the command-line option value.
*/
field += 1;
}
}
/*
* Add unmatched parameter.
*/
if ((mode & EDIT_CONF) && param_match == 0) {
/* XXX Generalize: argv_insert(argv, where, list...) */
argv_insert_one(argv, field, "-o");
aval = concatenate(param_name, "=",
param_value, (char *) 0);
argv_insert_one(argv, field + 1, aval);
if (masterp->all_params)
dict_put(masterp->all_params, param_name, param_value);
/* XXX May affect parameter "used/defined" status. */
myfree((char *) aval);
param_match = 1;
}
}

View File

@ -0,0 +1,188 @@
/*++
/* NAME
/* postconf_match 3
/* SUMMARY
/* pattern-matching support
/* SYNOPSIS
/* #include <postconf.h>
/*
/* int parse_field_pattern(field_expr)
/* char *field_expr;
/*
/* const char *str_field_pattern(field_pattern)
/* int field_pattern;
/*
/* int is_magic_field_pattern(field_pattern)
/* int field_pattern;
/*
/* ARGV *parse_service_pattern(service_expr, min_expr, max_expr)
/* const char *service_expr;
/* int min_expr;
/* int max_expr;
/*
/* int IS_MAGIC_SERVICE_PATTERN(service_pattern)
/* const ARGV *service_pattern;
/*
/* int MATCH_SERVICE_PATTERN(service_pattern, service_name,
/* service_type)
/* const ARGV *service_pattern;
/* const char *service_name;
/* const char *service_type;
/*
/* const char *str_field_pattern(field_pattern)
/* int field_pattern;
/*
/* int IS_MAGIC_PARAM_PATTERN(param_pattern)
/* const char *param_pattern;
/*
/* int MATCH_PARAM_PATTERN(param_pattern, param_name)
/* const char *param_pattern;
/* const char *param_name;
/* DESCRIPTION
/* parse_service_pattern() takes an expression and splits it
/* up on '/' into an array of sub-expressions, This function
/* returns null if the input does fewer than "min" or more
/* than "max" sub-expressions.
/*
/* IS_MAGIC_SERVICE_PATTERN() returns non-zero if any of the
/* service name or service type sub-expressions contains a
/* matching operator (as opposed to string literals that only
/* match themselves). This is an unsafe macro that evaluates
/* its arguments more than once.
/*
/* MATCH_SERVICE_PATTERN() matches a service name and type
/* from master.cf against the parsed pattern. This is an unsafe
/* macro that evaluates its arguments more than once.
/*
/* parse_field_pattern() converts a field sub-expression, and
/* returns the conversion result.
/*
/* str_field_pattern() converts a result from parse_field_pattern()
/* into string form.
/*
/* is_magic_field_pattern() returns non-zero if the field
/* pattern sub-expression contained a matching operator (as
/* opposed to a string literal that only matches itself).
/*
/* IS_MAGIC_PARAM_PATTERN() returns non-zero if the parameter
/* sub-expression contains a matching operator (as opposed to
/* a string literal that only matches itself). This is an
/* unsafe macro that evaluates its arguments more than once.
/*
/* MATCH_PARAM_PATTERN() matches a parameter name from master.cf
/* against the parsed pattern. This is an unsafe macro that
/* evaluates its arguments more than once.
/*
/* Arguments
/* .IP field_expr
/* A field expression.
/* .IP service_expr
/* This argument is split on '/' into its constituent
/* sub-expressions.
/* .IP min_expr
/* The minimum number of sub-expressions in service_expr.
/* .IP max_expr
/* The maximum number of sub-expressions in service_expr.
/* .IP service_name
/* Service name from master.cf.
/* .IP service_type
/* Service type from master.cf.
/* .IP param_pattern
/* A parameter name expression.
/* DIAGNOSTICS
/* Fatal errors: invalid syntax.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <vstring.h>
/* Global library. */
#include <split_at.h>
/* Application-specific. */
#include <postconf.h>
/*
* Conversion table. Each PC_MASTER_NAME_XXX name entry must be stored at
* table offset PC_MASTER_FIELD_XXX. So don't mess it up.
*/
NAME_CODE field_name_offset[] = {
PC_MASTER_NAME_SERVICE, PC_MASTER_FIELD_SERVICE,
PC_MASTER_NAME_TYPE, PC_MASTER_FIELD_TYPE,
PC_MASTER_NAME_PRIVATE, PC_MASTER_FIELD_PRIVATE,
PC_MASTER_NAME_UNPRIV, PC_MASTER_FIELD_UNPRIV,
PC_MASTER_NAME_CHROOT, PC_MASTER_FIELD_CHROOT,
PC_MASTER_NAME_WAKEUP, PC_MASTER_FIELD_WAKEUP,
PC_MASTER_NAME_MAXPROC, PC_MASTER_FIELD_MAXPROC,
PC_MASTER_NAME_CMD, PC_MASTER_FIELD_CMD,
"*", PC_MASTER_FIELD_WILDC,
0, PC_MASTER_FIELD_NONE,
};
/* parse_field_pattern - parse service attribute pattern */
int parse_field_pattern(const char *field_name)
{
int field_pattern;
if ((field_pattern = name_code(field_name_offset,
NAME_CODE_FLAG_STRICT_CASE,
field_name)) == PC_MASTER_FIELD_NONE)
msg_fatal("invalid service attribute name: \"%s\"", field_name);
return (field_pattern);
}
/* parse_service_pattern - parse service pattern */
ARGV *parse_service_pattern(const char *pattern, int min_expr, int max_expr)
{
ARGV *argv;
char **cpp;
/*
* Work around argv_split() lameness.
*/
if (*pattern == '/')
return (0);
argv = argv_split(pattern, PC_NAMESP_SEP_STR);
if (argv->argc < min_expr || argv->argc > max_expr) {
argv_free(argv);
return (0);
}
/*
* Allow '*' only all by itself.
*/
for (cpp = argv->argv; *cpp; cpp++) {
if (!PC_MATCH_ANY(*cpp) && strchr(*cpp, PC_MATCH_WILDC_STR[0]) != 0) {
argv_free(argv);
return (0);
}
}
/*
* Provide defaults for missing fields.
*/
while (argv->argc < max_expr)
argv_add(argv, PC_MATCH_WILDC_STR, ARGV_END);
return (argv);
}

View File

@ -45,13 +45,13 @@
/* set_config_dir - forcibly override var_config_dir */
void set_config_dir(void)
void set_config_dir(void)
{
char *config_dir;
if (var_config_dir)
myfree(var_config_dir);
myfree(var_config_dir);
var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
config_dir : DEF_CONFIG_DIR); /* XXX */
config_dir : DEF_CONFIG_DIR); /* XXX */
set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir);
}

View File

@ -0,0 +1,113 @@
/*++
/* NAME
/* postconf_print 3
/* SUMMARY
/* basic line printing support
/* SYNOPSIS
/* #include <postconf.h>
/*
/* void print_line(fp, mode, const char *fmt, ...)
/* VSTREAM *fp;
/* int mode;
/* const char *fmt;
/* DESCRIPTION
/* print_line() formats text, normalized whitespace, and
/* optionally folds long lines.
/*
/* Arguments:
/* .IP fp
/* Output stream.
/* .IP mode
/* Bit-wise OR of zero or more of the following (other flags
/* are ignored):
/* .RS
/* .IP FOLD_LINE
/* Fold long lines.
/* .RE
/* .IP fmt
/* Format string.
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
#include <stdarg.h>
/* Utility library. */
#include <msg.h>
#include <vstream.h>
#include <vstring.h>
/* Application-specific. */
#include <postconf.h>
/* SLMs. */
#define STR(x) vstring_str(x)
/* print_line - show line possibly folded, and with normalized whitespace */
void print_line(VSTREAM *fp, int mode, const char *fmt,...)
{
va_list ap;
static VSTRING *buf = 0;
char *start;
char *next;
int line_len = 0;
int word_len;
/*
* One-off initialization.
*/
if (buf == 0)
buf = vstring_alloc(100);
/*
* Format the text.
*/
va_start(ap, fmt);
vstring_vsprintf(buf, fmt, ap);
va_end(ap);
/*
* Normalize the whitespace. We don't use the line_wrap() routine because
* 1) that function does not normalize whitespace between words and 2) we
* want to normalize whitespace even when not wrapping lines.
*
* XXX Some parameters preserve whitespace: for example, smtpd_banner and
* smtpd_reject_footer. If we have to preserve whitespace between words,
* then perhaps readlline() can be changed to canonicalize whitespace
* that follows a newline.
*/
for (start = STR(buf); *(start += strspn(start, SEPARATORS)) != 0; start = next) {
word_len = strcspn(start, SEPARATORS);
if (*(next = start + word_len) != 0)
*next++ = 0;
if (word_len > 0 && line_len > 0) {
if ((mode & FOLD_LINE) == 0 || line_len + word_len < LINE_LIMIT) {
vstream_fputs(" ", fp);
line_len += 1;
} else {
vstream_fputs("\n" INDENT_TEXT, fp);
line_len = INDENT_LEN;
}
}
vstream_fputs(start, fp);
line_len += word_len;
}
vstream_fputs("\n", fp);
}

View File

@ -0,0 +1,2 @@
./postconf: warning: unmatched request: "bar/inet"
./postconf: warning: unmatched request: "foo/unix"

View File

@ -1,2 +1,4 @@
whatever unix - n n - 0 other
-o mydestination=yyy -o always_bcc=ccc -o aaa=ccc
-o mydestination=yyy
-o always_bcc=ccc
-o aaa=ccc

View File

@ -1,2 +1,6 @@
foo unix - n n - 0 other -v -o aaa=bbb -v
-o ccc=bbb -v -o ddd=bbb
foo unix - n n - 0 other -v
-o aaa=bbb
-v
-o ccc=bbb
-v
-o ddd=bbb

View File

@ -0,0 +1,12 @@
foo unix - n n - 0 other
bar unix - n n - 0 other
-o xxx=yyy
-o aaa=bbb
baz unix - n n - 0 other
foo unix - n n - 0 other
bar unix - n n - 0 other
-o xxx=YYY
-o aaa=BBB
baz unix - n n - 0 other
bar/unix/aaa = BBB
bar/unix/xxx = YYY

View File

@ -0,0 +1,10 @@
foo unix - n n - 0 other
bar unix - n n - 0 other
-o xxx=yyy
-o aaa=bbb
baz unix - n n - 0 other
bar/unix/aaa = bbb
bar/unix/xxx = yyy
foo unix - n n - 0 other
bar unix - n n - 0 other
baz unix - n n - 0 other

View File

@ -0,0 +1,5 @@
foo unix - n n - 0 other
bar unix - n y - 0 aa -stuff
-o bb=cc
dd
baz unix - n n - 0 other

View File

@ -0,0 +1,5 @@
foo unix - n n - 0 other
xx inet - n n - 0 aa -stuff
-o bb=cc
dd
baz unix - n n - 0 other

View File

@ -0,0 +1 @@
./postconf: fatal: invalid type field "xxxx" in "bar xxxx - n n - 0 other"

View File

@ -0,0 +1 @@
./postconf: fatal: invalid private field X" in "bar inet X n n - 0 other"

View File

@ -0,0 +1 @@
./postconf: fatal: invalid unprivileged field X" in "bar inet - X n - 0 other"

View File

@ -0,0 +1 @@
./postconf: fatal: invalid chroot field X" in "bar inet - n X - 0 other"

View File

@ -0,0 +1 @@
./postconf: fatal: invalid wakeup field X" in "bar inet - n n X 0 other"

View File

@ -0,0 +1 @@
./postconf: fatal: invalid process_limit field X" in "bar inet - n n - X other"

View File

@ -0,0 +1 @@
./postconf: fatal: invalid wakeup field X?" in "bar inet - n n X? 0 other"

View File

@ -0,0 +1 @@
baz unix - n n 0 0 other

View File

@ -0,0 +1,3 @@
foo unix - n n - 0 other
#bar inet - n n 0 0 other
baz unix - n n 0 0 other

View File

@ -0,0 +1,3 @@
#foo unix - n n - 0 other
#bar inet - n n 0 0 other
baz unix - n n 0 0 other

View File

@ -0,0 +1,3 @@
foo unix - n n - 0 other
#bar inet - n n 0 0 other
#baz unix - n n 0 0 other

View File

@ -0,0 +1,5 @@
foo unix - n n - 0 other
#bar inet - n n 0 0 other
# -o first
# -o second
baz unix - n n 0 0 other

View File

@ -798,7 +798,7 @@ static int doproto(STATE *state)
/* connect_sock - connect a socket over some transport */
static VSTREAM *connect_sock(int sock, struct sockaddr * sa, int salen,
static VSTREAM *connect_sock(int sock, struct sockaddr *sa, int salen,
const char *name, const char *addr, STATE *state)
{
DSN_BUF *why = state->why;
@ -895,7 +895,7 @@ static VSTREAM *connect_unix(STATE *state, const char *path)
if (msg_verbose)
msg_info("%s: trying: %s...", myname, path);
return (connect_sock(sock, (struct sockaddr *) & sock_un, sizeof(sock_un),
return (connect_sock(sock, (struct sockaddr *) &sock_un, sizeof(sock_un),
var_myhostname, path, state));
}
@ -906,7 +906,7 @@ static VSTREAM *connect_addr(STATE *state, DNS_RR *addr)
static const char *myname = "connect_addr";
DSN_BUF *why = state->why;
struct sockaddr_storage ss; /* remote */
struct sockaddr *sa = (struct sockaddr *) & ss;
struct sockaddr *sa = (struct sockaddr *) &ss;
SOCKADDR_SIZE salen = sizeof(ss);
MAI_HOSTADDR_STR hostaddr;
int sock;
@ -1392,7 +1392,7 @@ static int finger(STATE *state)
state->why = dsb_create();
if (!(err = connect_dest(state))) {
if (state->pass == 1)
if (state->pass == 1 && !state->nochat)
msg_info("Connected to %s", state->namaddrport);
err = doproto(state);
}
@ -1430,7 +1430,11 @@ static int finger(STATE *state)
static void ssl_cleanup(void)
{
ERR_remove_state(0);
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
ERR_remove_thread_state(0); /* Thread-id is now a pointer */
#else
ERR_remove_state(0); /* Deprecated with OpenSSL 1.0.0 */
#endif
ENGINE_cleanup();
CONF_modules_unload(1);
ERR_free_strings();
@ -1745,10 +1749,10 @@ static void parse_match(STATE *state, int argc, char *argv[])
argv_add(state->match, "hostname", ARGV_END);
break;
case TLS_LEV_FPRINT:
state->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED);
state->dane = tls_dane_alloc();
while (*argv)
tls_dane_split((TLS_DANE *) state->dane, TLS_DANE_EE, TLS_DANE_PKEY,
state->mdalg, *argv++, "");
tls_dane_add_ee_digests((TLS_DANE *) state->dane,
state->mdalg, *argv++, "");
break;
case TLS_LEV_DANE:
state->match = argv_alloc(2);
@ -1773,7 +1777,7 @@ static void parse_tas(STATE *state)
return;
case TLS_LEV_SECURE:
case TLS_LEV_VERIFY:
state->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED);
state->dane = tls_dane_alloc();
for (file = state->options.tas->argv; *file; ++file) {
if (!tls_dane_load_trustfile((TLS_DANE *) state->dane, *file))
break;

View File

@ -449,7 +449,7 @@
/* .IP "\fBsmtp_tls_force_insecure_host_tlsa_lookup (no)\fR"
/* Lookup the associated DANE TLSA RRset even when a hostname is
/* not an alias and its address records lie in an unsigned zone.
/* .IP "\fBtls_dane_trust_anchor_digest_enable (trust-anchor-assertion)\fR"
/* .IP "\fBtls_dane_trust_anchor_digest_enable (yes)\fR"
/* 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.

View File

@ -308,9 +308,9 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level,
break;
case TLS_LEV_FPRINT:
if (!tls->dane)
tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED);
tls_dane_split(tls->dane, TLS_DANE_EE, TLS_DANE_PKEY,
var_smtp_tls_fpt_dgst, val, "|");
tls->dane = tls_dane_alloc();
tls_dane_add_ee_digests(tls->dane,
var_smtp_tls_fpt_dgst, val, "|");
break;
case TLS_LEV_VERIFY:
case TLS_LEV_SECURE:
@ -345,7 +345,7 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level,
INVALID_RETURN(tls->why, site_level);
}
if (!tls->dane)
tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED);
tls->dane = tls_dane_alloc();
if (!tls_dane_load_trustfile(tls->dane, val)) {
INVALID_RETURN(tls->why, site_level);
}
@ -559,11 +559,10 @@ static void *policy_create(const char *unused_key, void *context)
break;
case TLS_LEV_FPRINT:
if (tls->dane == 0)
tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED);
tls->dane = tls_dane_alloc();
if (!TLS_DANE_HASEE(tls->dane)) {
tls_dane_split(tls->dane, TLS_DANE_EE, TLS_DANE_PKEY,
var_smtp_tls_fpt_dgst, var_smtp_tls_fpt_cmatch,
"\t\n\r, ");
tls_dane_add_ee_digests(tls->dane, var_smtp_tls_fpt_dgst,
var_smtp_tls_fpt_cmatch, "\t\n\r, ");
if (!TLS_DANE_HASEE(tls->dane)) {
msg_warn("nexthop domain %s: configured at fingerprint "
"security level, but with no fingerprints to match.",
@ -582,7 +581,7 @@ static void *policy_create(const char *unused_key, void *context)
"\t\n\r, :");
if (*var_smtp_tls_tafile) {
if (tls->dane == 0)
tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED);
tls->dane = tls_dane_alloc();
if (!TLS_DANE_HASTA(tls->dane)
&& !load_tas(tls->dane, var_smtp_tls_tafile)) {
MARK_INVALID(tls->why, &tls->level);

View File

@ -953,7 +953,8 @@
/* The location of the Postfix top-level queue directory.
/* .IP "\fBrecipient_delimiter (empty)\fR"
/* The set of characters that can separate a user name from its
/* address extension (user+foo).
/* extension (example: user+foo), or a .forward file name from its
/* extension (example: .forward+foo).
/* .IP "\fBsmtpd_banner ($myhostname ESMTP $mail_name)\fR"
/* The text that follows the 220 status code in the SMTP greeting
/* banner.

View File

@ -17,7 +17,7 @@ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
INCL =
LIB = libtls.a
TESTPROG= tls_dh tls_mgr
TESTPROG= tls_dh tls_mgr tls_rsa
LIBS = ../../lib/libglobal.a ../../lib/libutil.a
LIB_DIR = ../../lib
@ -81,6 +81,11 @@ tls_mgr: $(LIB) $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
mv junk $@.o
tls_rsa: $(LIB) $(LIBS)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
mv junk $@.o
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@ -151,7 +156,9 @@ tls_dane.o: ../../include/myaddrinfo.h
tls_dane.o: ../../include/mymalloc.h
tls_dane.o: ../../include/name_code.h
tls_dane.o: ../../include/name_mask.h
tls_dane.o: ../../include/safe_ultostr.h
tls_dane.o: ../../include/sock_addr.h
tls_dane.o: ../../include/split_at.h
tls_dane.o: ../../include/stringops.h
tls_dane.o: ../../include/sys_defs.h
tls_dane.o: ../../include/timecmp.h
@ -320,6 +327,7 @@ tls_proxy_scan.o: tls_proxy.h
tls_proxy_scan.o: tls_proxy_scan.c
tls_rsa.o: ../../include/argv.h
tls_rsa.o: ../../include/dns.h
tls_rsa.o: ../../include/msg.h
tls_rsa.o: ../../include/myaddrinfo.h
tls_rsa.o: ../../include/name_code.h
tls_rsa.o: ../../include/name_mask.h

View File

@ -82,6 +82,20 @@ extern const NAME_CODE tls_level_table[];
#if (OPENSSL_VERSION_NUMBER < 0x00090700f)
#error "need OpenSSL version 0.9.7 or later"
#endif
/* SSL_CIPHER_get_name() got constified in 0.9.7g */
#if OPENSSL_VERSION_NUMBER >= 0x0090707fL /* constification */
#define SSL_CIPHER_const const
#else
#define SSL_CIPHER_const
#endif
/* d2i_X509() got constified in 0.9.8a */
#if OPENSSL_VERSION_NUMBER >= 0x0090801fL
#define D2I_const const
#else
#define D2I_const
#endif
/*
@ -108,10 +122,9 @@ extern const NAME_CODE tls_level_table[];
#define TLS_DANE_CERT 0 /* Match the certificate digest */
#define TLS_DANE_PKEY 1 /* Match the public key digest */
#define TLS_DANE_FLAG_MIXED (1<<0) /* Combined pkeys and certs */
#define TLS_DANE_FLAG_NORRS (1<<1) /* Nothing found in DNS */
#define TLS_DANE_FLAG_EMPTY (1<<2) /* Nothing usable found in DNS */
#define TLS_DANE_FLAG_ERROR (1<<3) /* TLSA record lookup error */
#define TLS_DANE_FLAG_NORRS (1<<0) /* Nothing found in DNS */
#define TLS_DANE_FLAG_EMPTY (1<<1) /* Nothing usable found in DNS */
#define TLS_DANE_FLAG_ERROR (1<<2) /* TLSA record lookup error */
#define tls_dane_unusable(dane) ((dane)->flags & TLS_DANE_FLAG_EMPTY)
#define tls_dane_notfound(dane) ((dane)->flags & TLS_DANE_FLAG_NORRS)
@ -146,10 +159,6 @@ typedef struct TLS_PKEYS {
struct TLS_PKEYS *next;
} TLS_PKEYS;
/*
* When TLS_DANE_FLAG_MIXED is set, the pkeys digest list is not allocated
* separately, and aliases the certs digest list for each algorithm.
*/
typedef struct TLS_DANE {
TLS_TLSA *ta; /* Trust-anchor cert/pubkey digests */
TLS_TLSA *ee; /* End-entity cert/pubkey digests */
@ -170,9 +179,9 @@ typedef struct TLS_DANE {
extern int tls_dane_avail(void);
extern void tls_dane_flush(void);
extern void tls_dane_verbose(int);
extern TLS_DANE *tls_dane_alloc(int);
extern void tls_dane_split(TLS_DANE *, int, int, const char *, const char *,
const char *);
extern TLS_DANE *tls_dane_alloc(void);
extern void tls_dane_add_ee_digests(TLS_DANE *, const char *, const char *,
const char *);
extern void tls_dane_free(TLS_DANE *);
extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int);
extern int tls_dane_load_trustfile(TLS_DANE *, const char *);

View File

@ -756,7 +756,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
int protomask;
const char *cipher_list;
SSL_SESSION *session = 0;
const SSL_CIPHER *cipher;
SSL_CIPHER_const SSL_CIPHER *cipher;
X509 *peercert;
TLS_SESS_STATE *TLScontext;
TLS_APPL_STATE *app_ctx = props->ctx;
@ -788,9 +788,9 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
props->namaddr, props->protocols);
return (0);
}
/* The DANE level requires TLS 1.0 or later, not SSLv2 or SSLv3. */
/* The DANE level requires SSLv3 or later, not SSLv2. */
if (props->tls_level == TLS_LEV_DANE)
protomask |= TLS_PROTOCOL_SSLv3 | TLS_PROTOCOL_SSLv2;
protomask |= TLS_PROTOCOL_SSLv2;
/*
* Per session cipher selection for sessions with mandatory encryption

File diff suppressed because it is too large Load Diff

View File

@ -223,9 +223,6 @@ char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask,
* we must include the SNI name in the session id.
*/
if (props->dane) {
int mixed = (props->dane->flags & TLS_DANE_FLAG_MIXED);
digest_object(&mixed);
digest_dane(props->dane, ta);
#if 0
digest_dane(props->dane, ee); /* See above */

View File

@ -14,10 +14,11 @@
/* char *var_tls_null_clist;
/* char *var_tls_eecdh_strong;
/* char *var_tls_eecdh_ultra;
/* char *var_tls_dane_ta_dgst;
/* char *var_tls_dane_agility;
/* char *var_tls_dane_digests;
/* int var_tls_daemon_rand_bytes;
/* bool var_tls_append_def_CA;
/* bool var_tls_dane_taa_dgst;
/* bool var_tls_preempt_clist;
/* bool var_tls_bc_pkey_fprint;
/* bool var_tls_multi_wildcard;
@ -221,15 +222,15 @@ char *var_tls_null_clist;
int var_tls_daemon_rand_bytes;
char *var_tls_eecdh_strong;
char *var_tls_eecdh_ultra;
char *var_tls_dane_agility;
char *var_tls_dane_digests;
char *var_tls_dane_ta_dgst;
bool var_tls_append_def_CA;
char *var_tls_bug_tweaks;
char *var_tls_ssl_options;
bool var_tls_bc_pkey_fprint;
bool var_tls_dane_taa_dgst;
bool var_tls_multi_wildcard;
char *var_tls_mgr_service;
char *tls_dane_digests;
#ifdef VAR_TLS_PREEMPT_CLIST
bool var_tls_preempt_clist;
@ -264,59 +265,72 @@ static const NAME_CODE protocol_table[] = {
#define NAMEBUG(x) #x, SSL_OP_##x
static const LONG_NAME_MASK ssl_bug_tweaks[] = {
#if defined(SSL_OP_MICROSOFT_SESS_ID_BUG)
NAMEBUG(MICROSOFT_SESS_ID_BUG), /* 0x00000001L */
#ifndef SSL_OP_MICROSOFT_SESS_ID_BUG
#define SSL_OP_MICROSOFT_SESS_ID_BUG 0
#endif
NAMEBUG(MICROSOFT_SESS_ID_BUG),
#if defined(SSL_OP_NETSCAPE_CHALLENGE_BUG)
NAMEBUG(NETSCAPE_CHALLENGE_BUG), /* 0x00000002L */
#ifndef SSL_OP_NETSCAPE_CHALLENGE_BUG
#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0
#endif
NAMEBUG(NETSCAPE_CHALLENGE_BUG),
#if defined(SSL_OP_LEGACY_SERVER_CONNECT)
NAMEBUG(LEGACY_SERVER_CONNECT), /* 0x00000004L */
#ifndef SSL_OP_LEGACY_SERVER_CONNECT
#define SSL_OP_LEGACY_SERVER_CONNECT 0
#endif
NAMEBUG(LEGACY_SERVER_CONNECT),
#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)
NAMEBUG(NETSCAPE_REUSE_CIPHER_CHANGE_BUG), /* 0x00000008L */
#ifndef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0
#endif
NAMEBUG(NETSCAPE_REUSE_CIPHER_CHANGE_BUG),
"CVE-2010-4180", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG,
#endif
#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)
NAMEBUG(SSLREF2_REUSE_CERT_TYPE_BUG), /* 0x00000010L */
#ifndef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0
#endif
NAMEBUG(SSLREF2_REUSE_CERT_TYPE_BUG),
#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
NAMEBUG(MICROSOFT_BIG_SSLV3_BUFFER),/* 0x00000020L */
#ifndef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0
#endif
NAMEBUG(MICROSOFT_BIG_SSLV3_BUFFER),
#if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING)
NAMEBUG(MSIE_SSLV2_RSA_PADDING), /* 0x00000040L */
#ifndef SSL_OP_MSIE_SSLV2_RSA_PADDING
#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0
#endif
NAMEBUG(MSIE_SSLV2_RSA_PADDING),
"CVE-2005-2969", SSL_OP_MSIE_SSLV2_RSA_PADDING,
#endif
#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)
NAMEBUG(SSLEAY_080_CLIENT_DH_BUG), /* 0x00000080L */
#ifndef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0
#endif
NAMEBUG(SSLEAY_080_CLIENT_DH_BUG),
#if defined(SSL_OP_TLS_D5_BUG)
NAMEBUG(TLS_D5_BUG), /* 0x00000100L */
#ifndef SSL_OP_TLS_D5_BUG
#define SSL_OP_TLS_D5_BUG 0
#endif
NAMEBUG(TLS_D5_BUG),
#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG)
NAMEBUG(TLS_BLOCK_PADDING_BUG), /* 0x00000200L */
#ifndef SSL_OP_TLS_BLOCK_PADDING_BUG
#define SSL_OP_TLS_BLOCK_PADDING_BUG 0
#endif
NAMEBUG(TLS_BLOCK_PADDING_BUG),
#if defined(SSL_OP_TLS_ROLLBACK_BUG)
NAMEBUG(TLS_ROLLBACK_BUG), /* 0x00000400L */
#ifndef SSL_OP_TLS_ROLLBACK_BUG
#define SSL_OP_TLS_ROLLBACK_BUG 0
#endif
NAMEBUG(TLS_ROLLBACK_BUG),
#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
NAMEBUG(DONT_INSERT_EMPTY_FRAGMENTS), /* 0x00000800L */
#ifndef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0
#endif
NAMEBUG(DONT_INSERT_EMPTY_FRAGMENTS),
#if defined(SSL_OP_CRYPTOPRO_TLSEXT_BUG)
NAMEBUG(CRYPTOPRO_TLSEXT_BUG), /* 0x80000000L */
#ifndef SSL_OP_CRYPTOPRO_TLSEXT_BUG
#define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0
#endif
NAMEBUG(CRYPTOPRO_TLSEXT_BUG),
0, 0,
};
@ -328,17 +342,20 @@ static const LONG_NAME_MASK ssl_bug_tweaks[] = {
#define NAME_SSL_OP(x) #x, SSL_OP_##x
static const LONG_NAME_MASK ssl_op_tweaks[] = {
#if defined(SSL_OP_LEGACY_SERVER_CONNECT)
#ifndef SSL_OP_LEGACY_SERVER_CONNECT
#define SSL_OP_LEGACY_SERVER_CONNECT 0
#endif
NAME_SSL_OP(LEGACY_SERVER_CONNECT),
#endif
#if defined(SSL_OP_NO_TICKET)
#ifndef SSL_OP_NO_TICKET
#define SSL_OP_NO_TICKET 0
#endif
NAME_SSL_OP(NO_TICKET),
#endif
#if defined(SSL_OP_NO_COMPRESSION)
NAME_SSL_OP(NO_COMPRESSION),
#ifndef SSL_OP_NO_COMPRESSION
#define SSL_OP_NO_COMPRESSION 0
#endif
NAME_SSL_OP(NO_COMPRESSION),
0, 0,
};
@ -597,8 +614,8 @@ void tls_param_init(void)
VAR_TLS_EECDH_ULTRA, DEF_TLS_EECDH_ULTRA, &var_tls_eecdh_ultra, 1, 0,
VAR_TLS_BUG_TWEAKS, DEF_TLS_BUG_TWEAKS, &var_tls_bug_tweaks, 0, 0,
VAR_TLS_SSL_OPTIONS, DEF_TLS_SSL_OPTIONS, &var_tls_ssl_options, 0, 0,
VAR_TLS_DANE_AGILITY, DEF_TLS_DANE_AGILITY, &var_tls_dane_agility, 1, 0,
VAR_TLS_DANE_DIGESTS, DEF_TLS_DANE_DIGESTS, &var_tls_dane_digests, 1, 0,
VAR_TLS_DANE_TA_DGST, DEF_TLS_DANE_TA_DGST, &var_tls_dane_ta_dgst, 0, 0,
VAR_TLS_MGR_SERVICE, DEF_TLS_MGR_SERVICE, &var_tls_mgr_service, 1, 0,
0,
};
@ -609,6 +626,7 @@ void tls_param_init(void)
static const CONFIG_BOOL_TABLE bool_table[] = {
VAR_TLS_APPEND_DEF_CA, DEF_TLS_APPEND_DEF_CA, &var_tls_append_def_CA,
VAR_TLS_BC_PKEY_FPRINT, DEF_TLS_BC_PKEY_FPRINT, &var_tls_bc_pkey_fprint,
VAR_TLS_DANE_TAA_DGST, DEF_TLS_DANE_TAA_DGST, &var_tls_dane_taa_dgst,
VAR_TLS_PREEMPT_CLIST, DEF_TLS_PREEMPT_CLIST, &var_tls_preempt_clist,
VAR_TLS_MULTI_WILDCARD, DEF_TLS_MULTI_WILDCARD, &var_tls_multi_wildcard,
0,
@ -934,7 +952,8 @@ long tls_bug_bits(void)
{
long bits = SSL_OP_ALL; /* Work around all known bugs */
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && \
OPENSSL_VERSION_NUMBER < 0x10000000L
long lib_version = SSLeay();
/*
@ -960,6 +979,10 @@ long tls_bug_bits(void)
bits &= ~long_name_mask_opt(VAR_TLS_BUG_TWEAKS, ssl_bug_tweaks,
var_tls_bug_tweaks, NAME_MASK_ANY_CASE |
NAME_MASK_NUMBER | NAME_MASK_WARN);
#ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG
/* Not relevant to SMTP */
bits &= ~SSL_OP_SAFARI_ECDHE_ECDSA_BUG;
#endif
}
/*
@ -988,17 +1011,14 @@ void tls_print_errors(void)
const char *data;
int line;
int flags;
unsigned long thread;
thread = CRYPTO_thread_id();
while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
ERR_error_string_n(err, buffer, sizeof(buffer));
if (flags & ERR_TXT_STRING)
msg_warn("TLS library problem: %lu:%s:%s:%d:%s:",
thread, buffer, file, line, data);
msg_warn("TLS library problem: %s:%s:%d:%s:",
buffer, file, line, data);
else
msg_warn("TLS library problem: %lu:%s:%s:%d:",
thread, buffer, file, line);
msg_warn("TLS library problem: %s:%s:%d:", buffer, file, line);
}
}

View File

@ -12,10 +12,12 @@
/* int export;
/* int keylength;
/* DESCRIPTION
/* This module maintains parameters for Diffie-Hellman key generation.
/*
/* tls_tmp_rsa_cb() is a call-back routine for the
/* SSL_CTX_set_tmp_rsa_callback() function.
/*
/* This implementation will generate only 512-bit ephemeral
/* RSA keys for export ciphersuites. It will log a warning in
/* all other usage contexts.
/* LICENSE
/* .ad
/* .fi
@ -35,11 +37,14 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Viktor Dukhovni.
/*--*/
/* System library. */
#include <sys_defs.h>
#include <msg.h>
#ifdef USE_TLS
@ -50,25 +55,63 @@
/* tls_tmp_rsa_cb - call-back to generate ephemeral RSA key */
RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int unused_export, int keylength)
RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int export, int keylength)
{
static RSA *rsa_tmp;
/* Code adapted from OpenSSL apps/s_cb.c */
/*
* We generate ephemeral RSA keys only for export ciphersuites. In all
* other contexts use of ephemeral RSA keys violates the SSL/TLS
* protocol, and only takes place when applications ask for trouble and
* set the SSL_OP_EPHEMERAL_RSA option. Postfix should never do that.
*/
if (!export || keylength != 512) {
msg_warn("%sexport %d-bit ephemeral RSA key requested",
export ? "" : "non-", keylength);
return 0;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
if (rsa_tmp == 0) {
BIGNUM *e = BN_new();
if (e != 0 && BN_set_word(e, RSA_F4) && (rsa_tmp = RSA_new()) != 0)
if (!RSA_generate_key_ex(rsa_tmp, keylength, e, 0)) {
RSA_free(rsa_tmp);
rsa_tmp = 0;
}
if (e)
BN_free(e);
}
#else
if (rsa_tmp == 0)
rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
#endif
return (rsa_tmp);
}
#ifdef TEST
int main(int unused_argc, char **unused_argv)
#include <msg_vstream.h>
int main(int unused_argc, char *const argv[])
{
tls_tmp_rsa_cb(0, 1, 512);
tls_tmp_rsa_cb(0, 1, 1024);
tls_tmp_rsa_cb(0, 1, 2048);
tls_tmp_rsa_cb(0, 0, 512);
RSA *rsa;
int ok;
msg_vstream_init(argv[0], VSTREAM_ERR);
/* Export at 512-bits should work */
rsa = tls_tmp_rsa_cb(0, 1, 512);
ok = rsa != 0 && RSA_size(rsa) == 512 / 8;
ok = ok && PEM_write_RSAPrivateKey(stdout, rsa, 0, 0, 0, 0, 0);
tls_print_errors();
/* Non-export or unexpected bit length should fail */
ok = ok && tls_tmp_rsa_cb(0, 0, 512) == 0;
ok = ok && tls_tmp_rsa_cb(0, 1, 1024) == 0;
return ok ? 0 : 1;
}
#endif

View File

@ -183,8 +183,8 @@ static SSL_SESSION *get_server_session_cb(SSL *ssl, unsigned char *session_id,
do { \
buf = vstring_alloc(2 * (len + strlen(service))); \
hex_encode(buf, (char *) (id), (len)); \
vstring_sprintf_append(buf, "&s=%s", (service)); \
vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \
vstring_sprintf_append(buf, "&s=%s", (service)); \
vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \
} while (0)
@ -797,7 +797,7 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
{
const SSL_CIPHER *cipher;
SSL_CIPHER_const SSL_CIPHER *cipher;
X509 *peer;
char buf[CCERT_BUFSIZ];

View File

@ -115,7 +115,8 @@
/* addresses that have no ".domain" information.
/* .IP "\fBrecipient_delimiter (empty)\fR"
/* The set of characters that can separate a user name from its
/* address extension (user+foo).
/* extension (example: user+foo), or a .forward file name from its
/* extension (example: .forward+foo).
/* .IP "\fBswap_bangpath (yes)\fR"
/* Enable the rewriting of "site!user" into "user@site".
/* .PP

View File

@ -41,6 +41,11 @@
/* ssize_t pos;
/* const char *arg;
/*
/* void argv_delete(argvp, pos, how_many)
/* ARGV *argvp;
/* ssize_t pos;
/* ssize_t how_many;
/*
/* void ARGV_FAKE_BEGIN(argv, arg)
/* const char *arg;
/*
@ -85,6 +90,10 @@
/* argv_replace_one() replaces one string at the specified
/* position.
/*
/* argv_delete() deletes the specified number of elements
/* starting at the specified array position. The result is
/* null-terminated.
/*
/* ARGV_FAKE_BEGIN/END are an optimization for the case where
/* a single string needs to be passed into an ARGV-based
/* interface. ARGV_FAKE_BEGIN() opens a statement block and
@ -292,3 +301,23 @@ void argv_replace_one(ARGV *argvp, ssize_t where, const char *arg)
myfree(argvp->argv[where]);
argvp->argv[where] = mystrdup(arg);
}
/* argv_delete - remove string(s) from array */
void argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many)
{
ssize_t pos;
/*
* Sanity check.
*/
if (first < 0 || how_many < 0 || first + how_many > argvp->argc)
msg_panic("argv_delete bad range: (start=%ld count=%ld)",
(long) first, (long) how_many);
for (pos = first; pos < first + how_many; pos++)
myfree(argvp->argv[pos]);
for (pos = first; pos <= argvp->argc - how_many; pos++)
argvp->argv[pos] = argvp->argv[pos + how_many];
argvp->argc -= how_many;
}

View File

@ -28,6 +28,7 @@ extern void argv_terminate(ARGV *);
extern void argv_truncate(ARGV *, ssize_t);
extern void argv_insert_one(ARGV *, ssize_t, const char *);
extern void argv_replace_one(ARGV *, ssize_t, const char *);
extern void argv_delete(ARGV *, ssize_t, ssize_t);
extern ARGV *argv_free(ARGV *);
extern ARGV *argv_split(const char *, const char *);

View File

@ -8,9 +8,11 @@
/*
/* ARGV *argv_split(string, delim)
/* const char *string;
/* const char *delim;
/*
/* ARGV *argv_split_count(string, delim, count)
/* const char *string;
/* const char *delim;
/* ssize_t count;
/*
/* ARGV *argv_split_append(argv, string, delim)

View File

@ -115,7 +115,7 @@ const char *host_port(char *buf, char **host, char *def_host,
char *cp = buf;
int ipv6 = 0;
/*
/*-
* [host]:port, [host]:, [host].
* [ipv6:ipv6addr]:port, [ipv6:ipv6addr]:, [ipv6:ipv6addr].
*/

View File

@ -296,8 +296,8 @@ static int slmdb_recover(SLMDB *slmdb, int status)
MDB_envinfo info;
/*
* Recover bulk transactions only if they can be restarted. Limit
* the number of recovery attempts per slmdb(3) API request.
* Recover bulk transactions only if they can be restarted. Limit the
* number of recovery attempts per slmdb(3) API request.
*/
if ((slmdb->txn != 0 && slmdb->longjmp_fn == 0)
|| ((slmdb->api_retry_count += 1) >= slmdb->api_retry_limit))