From 99a79e64b21c60365375d74054eb34b8c54c49c6 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Mon, 23 Jan 2006 00:00:00 -0500 Subject: [PATCH] postfix-2.3-20060123 --- postfix/HISTORY | 116 +++++- postfix/README_FILES/CDB_README | 4 +- postfix/README_FILES/OVERVIEW | 13 +- postfix/README_FILES/SMTPD_POLICY_README | 12 +- postfix/README_FILES/TLS_README | 233 +++++++---- postfix/RELEASE_NOTES | 44 +- postfix/html/CDB_README.html | 8 +- postfix/html/OVERVIEW.html | 4 +- postfix/html/SMTPD_POLICY_README.html | 46 ++- postfix/html/TLS_README.html | 388 ++++++++++++------ postfix/html/cleanup.8.html | 131 +++--- postfix/html/flush.8.html | 8 +- postfix/html/pickup.8.html | 6 +- postfix/html/postalias.1.html | 139 ++++--- postfix/html/postconf.5.html | 124 +++--- postfix/html/postdrop.1.html | 12 +- postfix/html/postmap.1.html | 22 +- postfix/html/postqueue.1.html | 12 +- postfix/html/proxymap.8.html | 8 +- postfix/html/qmqpd.8.html | 6 +- postfix/html/scache.8.html | 6 +- postfix/html/sendmail.1.html | 186 ++++----- postfix/html/smtpd.8.html | 2 +- postfix/html/tlsmgr.8.html | 6 +- postfix/html/trivial-rewrite.8.html | 8 +- postfix/html/virtual.8.html | 12 +- postfix/man/Makefile.in | 80 ++-- postfix/man/man1/postalias.1 | 11 +- postfix/man/man1/postmap.1 | 14 +- postfix/man/man1/sendmail.1 | 6 +- postfix/man/man5/postconf.5 | 112 ++--- postfix/man/man8/cleanup.8 | 4 +- postfix/man/man8/virtual.8 | 4 +- postfix/mantools/dehtml | 9 + postfix/mantools/postlink | 2 +- postfix/proto/CDB_README.html | 8 +- postfix/proto/SMTPD_POLICY_README.html | 16 +- postfix/proto/TLS_README.html | 302 ++++++++++---- postfix/proto/postconf.proto | 124 +++--- postfix/src/anvil/anvil.c | 50 +-- postfix/src/bounce/bounce.c | 18 +- postfix/src/cleanup/cleanup.c | 8 +- postfix/src/cleanup/cleanup_init.c | 14 +- postfix/src/flush/flush.c | 10 +- postfix/src/global/Makefile.in | 52 ++- postfix/src/global/abounce.c | 14 +- postfix/src/global/anvil_clnt.c | 36 +- postfix/src/global/bounce.c | 22 +- postfix/src/global/defer.c | 16 +- postfix/src/global/deliver_pass.c | 10 +- postfix/src/global/deliver_request.c | 10 +- postfix/src/global/dict_ldap.c | 12 + postfix/src/global/dict_mysql.c | 15 +- postfix/src/global/dict_pgsql.c | 14 + postfix/src/global/dict_proxy.c | 20 +- postfix/src/global/dsn_mask.c | 5 +- postfix/src/global/ehlo_mask.ref | 6 +- postfix/src/global/mail_addr_find.c | 7 +- postfix/src/global/mail_addr_map.c | 2 +- postfix/src/global/mail_command_client.c | 2 +- postfix/src/global/mail_stream.c | 4 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/maps.c | 13 +- postfix/src/global/post_mail.c | 4 +- postfix/src/global/rcpt_buf.c | 2 +- postfix/src/global/rcpt_print.c | 2 +- postfix/src/global/resolve_clnt.c | 4 +- postfix/src/global/rewrite_clnt.c | 2 +- postfix/src/global/scache_clnt.c | 12 +- postfix/src/global/trace.c | 10 +- postfix/src/global/verify_clnt.c | 8 +- postfix/src/global/virtual8.in | 8 - postfix/src/global/virtual8.ref | 8 - postfix/src/global/virtual8_map | 3 - postfix/src/global/virtual8_maps.c | 163 -------- postfix/src/global/virtual8_maps.h | 38 -- postfix/src/local/forward.c | 4 +- postfix/src/local/local.c | 3 +- postfix/src/local/mailbox.c | 8 +- postfix/src/local/unknown.c | 4 +- postfix/src/master/multi_server.c | 5 + postfix/src/master/single_server.c | 5 + postfix/src/master/trigger_server.c | 5 + postfix/src/oqmgr/qmgr_deliver.c | 10 +- postfix/src/pickup/pickup.c | 4 +- postfix/src/postalias/postalias.c | 68 +-- postfix/src/postdrop/postdrop.c | 2 +- postfix/src/postmap/postmap.c | 71 ++-- postfix/src/postqueue/Makefile.in | 1 + postfix/src/postqueue/postqueue.c | 1 + postfix/src/proxymap/proxymap.c | 16 +- postfix/src/qmgr/qmgr_deliver.c | 10 +- postfix/src/qmqpd/qmqpd.c | 2 +- postfix/src/scache/scache.c | 28 +- postfix/src/sendmail/sendmail.c | 6 +- postfix/src/smtp/Makefile.in | 8 +- postfix/src/smtp/legacy.c | 205 +++++++++ postfix/src/smtp/levels.c | 189 +++++++++ postfix/src/smtp/smtp.c | 2 +- postfix/src/smtp/smtp.h | 20 +- postfix/src/smtp/smtp_addr.c | 2 +- postfix/src/smtp/smtp_connect.c | 6 +- postfix/src/smtp/smtp_map11.c | 2 +- postfix/src/smtp/smtp_proto.c | 18 +- postfix/src/smtp/smtp_sasl_glue.c | 5 +- postfix/src/smtp/smtp_session.c | 188 +++++---- postfix/src/smtp/tls_policy.in | 64 +++ postfix/src/smtp/tls_policy.ref | 65 +++ postfix/src/smtpd/Makefile.in | 5 +- postfix/src/smtpd/smtpd.c | 38 +- postfix/src/smtpd/smtpd.h | 20 + postfix/src/smtpd/smtpd_check.c | 111 ++--- postfix/src/smtpd/smtpd_check.ref | 12 +- postfix/src/smtpd/smtpd_check.ref2 | 8 +- postfix/src/smtpd/smtpd_check_dsn.ref | 18 +- postfix/src/smtpd/smtpd_dsn_fix.c | 6 +- postfix/src/smtpd/smtpd_dsn_fix.h | 7 + postfix/src/spawn/Makefile.in | 1 + postfix/src/tls/tls_mgr.c | 20 +- postfix/src/tls/tls_verify.c | 62 ++- postfix/src/tlsmgr/tlsmgr.c | 22 +- postfix/src/trivial-rewrite/resolve.c | 6 +- postfix/src/trivial-rewrite/rewrite.c | 2 +- postfix/src/trivial-rewrite/transport.c | 40 +- postfix/src/trivial-rewrite/trivial-rewrite.c | 8 +- postfix/src/util/Makefile.in | 11 + postfix/src/util/attr.h | 5 +- postfix/src/util/attr_clnt.c | 5 +- postfix/src/util/attr_print0.c | 8 +- postfix/src/util/attr_print64.c | 8 +- postfix/src/util/attr_print_plain.c | 8 +- postfix/src/util/attr_scan0.c | 12 +- postfix/src/util/attr_scan64.c | 13 +- postfix/src/util/attr_scan_plain.c | 13 +- postfix/src/util/auto_clnt.c | 12 + postfix/src/util/auto_clnt.h | 1 + postfix/src/util/dict.c | 42 ++ postfix/src/util/dict.h | 10 +- postfix/src/util/dict_alloc.c | 3 +- postfix/src/util/dict_cdb.c | 25 ++ postfix/src/util/dict_db.c | 28 ++ postfix/src/util/dict_dbm.c | 28 ++ postfix/src/util/dict_env.c | 26 +- postfix/src/util/dict_ni.c | 12 + postfix/src/util/dict_nis.c | 13 + postfix/src/util/dict_nisplus.c | 12 + postfix/src/util/dict_open.c | 20 +- postfix/src/util/dict_pcre.c | 21 +- postfix/src/util/dict_regexp.c | 15 +- postfix/src/util/dict_sdbm.c | 28 ++ postfix/src/util/dict_tcp.c | 11 + postfix/src/util/dict_unix.c | 24 +- postfix/src/util/htable.c | 3 + postfix/src/util/match_list.c | 5 +- postfix/src/util/match_ops.c | 32 +- postfix/src/util/myaddrinfo.ref | 4 +- postfix/src/util/name_mask.c | 26 +- postfix/src/util/name_mask.h | 10 +- postfix/src/util/unescape.c | 2 +- postfix/src/verify/verify.c | 12 +- postfix/src/virtual/virtual.c | 7 +- postfix/src/xsasl/Makefile.in | 2 + 162 files changed, 3138 insertions(+), 1666 deletions(-) create mode 100755 postfix/mantools/dehtml delete mode 100644 postfix/src/global/virtual8.in delete mode 100644 postfix/src/global/virtual8.ref delete mode 100644 postfix/src/global/virtual8_map delete mode 100644 postfix/src/global/virtual8_maps.c delete mode 100644 postfix/src/global/virtual8_maps.h create mode 100644 postfix/src/smtp/legacy.c create mode 100644 postfix/src/smtp/levels.c create mode 100644 postfix/src/smtp/tls_policy.in create mode 100644 postfix/src/smtp/tls_policy.ref diff --git a/postfix/HISTORY b/postfix/HISTORY index 8a4f3200f..7d3de16e4 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -11823,14 +11823,123 @@ Apologies for any names omitted. bounce/bounce_one_service.c, bounce/bounce_notify_verp.c, bounce/bounce_warn_service.c, bounce/bounce_trace_service.c. + Fudge: when translating recipient DSN codes into sender DSN + codes, map sender address problems that have no DSN code + to *.1.7 (Bad sender's mailbox address syntax) instead of + *.1.0 (Other address status) because that loses the distinction + between sender and recipient. File: smtpd/smtpd_dsn_fix.c. + +20060113 + + Cleanup: preserve upper case information of address localpart + or extension when mapping one address to another with + non-regexp/pcre tables. Files: global/mail_addr_find.c, + global/maps_find.c. + +20060115 + + Bugfix: don't ignore the per-site policy when SSL library + initialization fails. Introduced after adopting the TLS + patch. File: smtp/smtp_session.c. + +20060117 + + Safety: daemon processes that need no privileges now insist + that they are configured to run without privileges. Files: + master/single_server.c, master/multi_server.c, + master/trigger_server.c. + + Cleanup: preserve upper case information of address localpart + or extension when mapping addresses via regexp/pcre tables. + This requires that Postfix does not case fold the search + string when searching regexp or pcre tables, so that $number + substitutions produce the expected result. + + In order to get a consistent handling of table operations, + the search string case folding logic was moved from the + application to the individual lookup table modules; the + application specifies its case folding preference when it + opens a table, and the table folds the search or update + string as needed. + + Files: everything that opens a map or multiple maps (to + specify the case folding preference), and everything that + contained ad-hoc code to lowercase search strings (which + is no longer needed). + + Bugfix: as a side effect of this revision of all code that + opens tables, the postmap/postalias -n/-N options are no + longer silently ignored when the -q (query) and -d (delete) + options are specified. Files: postmap/postmap.c, + postalias/postalias.c. + + Cleanup: smtp_sasl_passwd_maps lookup keys are folded to + lowercase before searching tables such as btree:, dbm: or + hash: that have fixed-case fields. File: smtp/smtp_sasl_glue.c. + + Bugfix: per-sender relayhost maps were not locked for shared + access. + +20060119 + + Cleanup: don't look up parent domain substrings in regexp/pcre + like tables while searching a hostname in a domain/namaddr_list. + File: util/match_ops.c. + +20060120 + + Cleanup: multiple boolean variables were replaced by a + single TLS enforcement level (none, may, encrypt, verify). + With Victor Duchovni. Files: smtp_session.c, smtp_proto.c, + smtp.h. + + Cleanup: the SMTP per-site policy table was re-implemented + in terms of enforcement levels instead of multiple boolean + variables. This greatly simplified the code and led to the + elimination of non-intuitive behavior as documented next. + With Victor Duchovni. Files: smtp_session.c, smtp.h. + + Bugfix: a per-site MUST_NOPEERMATCH policy could not override + a main.cf MUST (with peer match) policy. + + Bugfix: a combined TLS per-site (host, next-hop) policy of + (NONE, MAY) would change the strongest main.cf MUST policy + into NONE, while it changed all weaker main.cf policies + into MAY. The result is now NONE for all main.cf policy + settings. + +20060123 + + Feature: recipient_count attribute in SMTPD policy protocol. + This is available only in the DATA and END-OF-MESSAGE stage. + Based on code by Guo Black. Files: smtpd_check.c. + + Cleanup: renamed MUMBLE_NUM to MUMBLE_INT to make type + discrepancies more explicit. + + Bugfix: change 20051208 broke when a connection could not + be established. File: util/auto_clnt.c. + Open problems: + Centralize main.cf parameter input so that defaults work + consistently. + + In second-line servers such as proxymap and trivial-rewrite, + set the max_idle time limit to a relatively small value so + that processes will refresh more often. + + After the 20051222 ISASCII paranoia, lowercase() lowercases + ASCII text only. + Privacy: remove local command/pathname details from remote delivery status reports, and log them via local msg_warn(). Remove defer(8) and trace(8) references and man pages. These are services not program names. + dsb_formal -> dsb_form_all, dsb_status -> dsb_form_status + "postsuper -r" no longer resets the message arrival time, because pickup(8) no longer overrides queue file time stamp information. This can be a problem when mail "on hold" is @@ -11849,11 +11958,6 @@ Open problems: deferred queue scan needs to be done, and have the pickup server stat() the maildrop directory before searching it. - Mapping from errno to diagnostic text. Or do we just slap - an SMTP code in front of what is now reported as X-Postfix. - Or do we punt the issue and issue X-Postfix for all errors - except SMTP? - Low: replace_sender/replace_recipient actions in access maps? @@ -11898,8 +12002,6 @@ Open problems: Med: the TLS certificate verification depth parameters never worked. - Med: eliminate the tls_info data structure. - Low: reject HELO with any domain name or IP address that this MTA is the final destination for. diff --git a/postfix/README_FILES/CDB_README b/postfix/README_FILES/CDB_README index 8c32ee4dd..0d00bf59a 100644 --- a/postfix/README_FILES/CDB_README +++ b/postfix/README_FILES/CDB_README @@ -33,7 +33,7 @@ Postfix is compatible with two CDB implementations: Tinycdb is preferred, since it is a bit faster, has additional useful functionality and is much simpler to use. -To build Postfix after you have installed CDB, use something like: +To build Postfix after you have installed tinycdb, use something like: % make tidy % CDB=../../../tinycdb-0.5 @@ -41,7 +41,7 @@ To build Postfix after you have installed CDB, use something like: "AUXLIBS=$CDB/libcdb.a" % make - for tinycdb, or alternatively, for the D.J.B. version: +Alternatively, for the D.J.B. version of CDB: % make tidy % CDB=../../../cdb-0.75 diff --git a/postfix/README_FILES/OVERVIEW b/postfix/README_FILES/OVERVIEW index c9d40269f..1d9ae180f 100644 --- a/postfix/README_FILES/OVERVIEW +++ b/postfix/README_FILES/OVERVIEW @@ -210,12 +210,11 @@ queues. Network -> smtpd(8) <-> anvil(8) - * The bounce(8) server implements the bounce, defer and trace services, which - maintain separate directory trees with per-message logfiles. This - information is used to send delivery or non-delivery notifications to the - sender. + * The bounce(8), defer(8) and trace(8) servers each maintain their own queue + directory trees with per-message logfiles. This information is used to send + delivery or non-delivery notifications to the sender. - The trace service implements support for the Postfix "sendmail -bv" and + The trace(8) service implements support for the Postfix "sendmail -bv" and "sendmail -v" commands which produce reports about how Postfix delivers mail, and is available with Postfix version 2.1 and later. See DEBUG_README for examples. @@ -228,8 +227,8 @@ queues. | v v (Non-) bounce(8) Queue id, - delivery <- defer <- recipient, - notice trace status + delivery <- defer(8) <- recipient, + notice trace(8) status ^ | | v diff --git a/postfix/README_FILES/SMTPD_POLICY_README b/postfix/README_FILES/SMTPD_POLICY_README index ecaa5151a..e58508cdd 100644 --- a/postfix/README_FILES/SMTPD_POLICY_README +++ b/postfix/README_FILES/SMTPD_POLICY_README @@ -47,6 +47,7 @@ a delegated SMTPD access policy request: queue_id=8045F2AB23 sender=foo@bar.tld recipient=bar@foo.tld + recipient_count=0 client_address=1.2.3.4 client_name=another.domain.tld reverse_client_name=another.domain.tld @@ -77,7 +78,16 @@ Notes: the first value or the last attribute value. * When an attribute value is unavailable, the client either does not send the - attribute, or sends the attribute with an empty value ("name="). + attribute, sends the attribute with an empty value ("name="), or sends a + zero value ("name=0") in the case of a numerical attribute. + + * The "recipient" attribute is available only in the "RCPT TO" stage, and in + the "DATA" and "END-OF-MESSAGE" stages when Postfix accepted only one + recipient for the current message. + + * The "recipient_count" attribute (Postfix 2.3 and later) is non-zero only in + the "DATA" and "END-OF-MESSAGE" stages. It specifies the number of + recipients that Postfix accepted for the current message. * The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6. diff --git a/postfix/README_FILES/TLS_README b/postfix/README_FILES/TLS_README index 676b4005a..e30f9fbbe 100644 --- a/postfix/README_FILES/TLS_README +++ b/postfix/README_FILES/TLS_README @@ -68,6 +68,10 @@ To build Postfix with TLS support, first we need to generate the make(1) files with the necessary definitions. This is done by invoking the command "make makefiles" in the Postfix top-level directory and with arguments as shown next. +NNOOTTEE:: DDoo nnoott uussee GGnnuu TTLLSS.. IItt wwiillll ssppoonnttaanneeoouussllyy tteerrmmiinnaattee aa pprroocceessss wwiitthh eexxiitt +ssttaattuuss ccooddee 22,, iinnsstteeaadd ooff pprrooppeerrllyy rreeppoorrttiinngg pprroobblleemmss ttoo PPoossttffiixx,, ssoo tthhaatt iitt +ccaann lloogg tthheemm ttoo tthhee mmaaiilllloogg ffiillee.. + * If the OpenSSL include files (such as ssl.h) are in directory /usr/include/ openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/lib: @@ -487,7 +491,12 @@ Topics covered in this section: * Client-side TLS activity logging * Client-side TLS session cache * Enabling TLS in the Postfix SMTP client - * Server certificate verification + * Requiring TLS encryption + * Disabling server certificate verification + * Per-site TLS policies + * Closing a DNS loophole with per-site TLS policies + * Discovering servers that support TLS + * Server certificate verification depth * Client-side cipher controls * Miscellaneous client controls @@ -532,12 +541,12 @@ If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, -unless $smtp_tls_verify_depth is less than the number of CAs in the certificate -chain for the servers of interest. With a verify depth of 1 you can only verify -certificates directly signed by a trusted CA, and all trusted intermediary CAs -need to be configured explicitly. With a verify depth of 2 you can verify -servers signed by a root CA or a direct intermediary CA (so long as the server -is correctly configured to supply its intermediate CA certificate). +unless $smtp_tls_scert_verifydepth is less than the number of CAs in the +certificate chain for the servers of interest. With a verify depth of 1 you can +only verify certificates directly signed by a trusted CA, and all trusted +intermediary CAs need to be configured explicitly. With a verify depth of 2 you +can verify servers signed by a root CA or a direct intermediary CA (so long as +the server is correctly configured to supply its intermediate CA certificate). RSA key and certificate examples: @@ -635,20 +644,19 @@ By default, TLS is disabled in the Postfix SMTP client, so no difference to plain Postfix is visible. If you enable TLS, the Postfix SMTP client will send STARTTLS when TLS support is announced by the remote SMTP server. -WARNING: MS Exchange servers will announce STARTTLS support even when the -service is not configured, so that the TLS handshake will fail. It may be wise -to not use this option on your central mail hub, as you don't know in advance -whether you are going to connect to such a host. Instead, use the -smtp_tls_per_site recipient/site specific options that are described below. - -When the TLS handshake fails and no other server is available, the Postfix SMTP -client defers the delivery attempt, and the mail stays in the queue. +When the server accepts the STARTTLS command, but the subsequent TLS handshake +fails, and no other server is available, the Postfix SMTP client defers the +delivery attempt, and the mail stays in the queue. After a handshake failure, +the communications channel is in an indeterminate state and cannot be used for +non-TLS deliveries. Example: /etc/postfix/main.cf: smtp_use_tls = yes +RReeqquuiirriinngg TTLLSS eennccrryyppttiioonn + You can ENFORCE the use of TLS, so that the Postfix SMTP client will not deliver mail over unencrypted connections. In this mode, the remote SMTP server hostname must match the information in the remote server certificate, and the @@ -657,21 +665,22 @@ client. If the remote server certificate doesn't verify or the remote SMTP server hostname doesn't match, and no other server is available, the delivery attempt is deferred and the mail stays in the queue. -The remote SMTP server hostname used in the check is beyond question, as it -must be the principal hostname (no CNAME allowed here). Checks are performed -against all names provided as dNSNames in the SubjectAlternativeName. If no -dNSNames are specified, the CommonName is checked. The behavior may be changed -with the smtp_tls_enforce_peername option which is discussed below. +The remote SMTP server hostname is verified against all names provided as +dNSNames in the SubjectAlternativeName. If no dNSNames are specified, the +CommonName is checked. Verification may be turned off with the +smtp_tls_enforce_peername option which is discussed below. -This option is useful only if you know that you will only connect to servers -that support RFC 2487 _and_ that present server certificates that meet the -above requirements. An example would be a client only sends email to one +Enforcing the use of TLS is useful if you know that you will only connect to +servers that support RFC 2487 _and_ that present server certificates that meet +the above requirements. An example would be a client only sends email to one specific mailhub that offers the necessary STARTTLS support. Example: /etc/postfix/main.cf: - smtp_enforce_tls = no + smtp_enforce_tls = yes + +DDiissaabblliinngg sseerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn As of RFC 2487 the requirements for hostname checking for MTA clients are not set. When TLS is required (smtp_enforce_tls = yes), the option @@ -679,79 +688,138 @@ smtp_tls_enforce_peername can be set to "no" to disable strict remote SMTP server hostname checking. In this case, the mail delivery will proceed regardless of the CommonName etc. listed in the certificate. -Note: the smtp_tls_enforce_peername setting has no effect on sessions that are -controlled via the smtp_tls_per_site table. - -Disabling the remote SMTP server hostname verification can make sense in closed -environment where special CAs are created. If not used carefully, this option -opens the danger of a "man-in-the-middle" attack (the CommonName of this -possible attacker is logged). +Despite the potential for eliminating "man-in-the-middle" and other attacks, +mandatory certificate/peername verification is not viable as a default Internet +mail delivery policy at this time. A significant fraction of TLS enabled MTAs +uses self-signed certificates, or certificates that are signed by a private +certificate authority. On a machine that delivers mail to the Internet, if you +set smtp_enforce_tls = yes, you should probably also set +smtp_tls_enforce_peername = no. You can use the per-site TLS policies (see +below) to enable full peer verification for specific destinations that are +known to have verifiable TLS server certificates. Example: /etc/postfix/main.cf: - smtp_tls_enforce_peername = yes + smtp_enforce_tls = yes + smtp_tls_enforce_peername = no -Generally, trying TLS can be a bad idea, as some servers offer STARTTLS but the -negotiation will fail leading to unexplainable failures. Instead, it may be a -good idea to choose the TLS usage policy based on the recipient or the mailhub -to which you are connecting. +PPeerr--ssiittee TTLLSS ppoolliicciieess -Deciding the TLS usage policy per recipient may be difficult, since a single -email delivery attempt can involve several recipients. Instead, use of TLS is -controlled by the Postfix next-hop destination domain name and by the remote -SMTP server hostname. If either of these matches an entry in the -smtp_tls_per_site table, appropriate action is taken. +A small fraction of servers offer STARTTLS but the negotiation consistently +fails, leading to mail aging out of the queue and bouncing back to the sender. +In such cases, you can use the per-site policies to disable TLS for the problem +sites. Alternatively, you can enable TLS for just a few specific sites and not +enable it for all sites. -The remote SMTP server hostname is simply the DNS name of the server that the -Postfix SMTP client connects to. The next-hop destination is Postfix specific. -By default, this is the domain name in the recipient address, but this -information can be overruled by the transport(5) table or by the relayhost -parameter setting. In these cases the relayhost etc. must be listed in the -smtp_tls_per_site table, instead of the recipient domain name. +The smtp_tls_per_site table is searched for a policy that matches the following +information: -Format of the table: domain or host names are specified on the left-hand side; -no wildcards are allowed. On the right hand side specify one of the following -keywords: + remote SMTP server hostname + This is simply the DNS name of the server that the Postfix SMTP client + connects to; this name may be obtained from other DNS lookups, such as + MX lookups or CNAME lookups. + next-hop destination + This is normally the domain portion of the recipient address, but it + may be overruled by information from the transport(5) table, from the + relayhost parameter setting, or from the relay_transport setting. When + it's not the recipient domain, the next-hop destination can have the + Postfix-specific form "[name]", [name]:port", "name" or "name:port". + +When both the hostname lookup and the next-hop lookup succeed, the host policy +does not automatically override the next-hop policy. Instead, precedence is +given to either the more specific or the more secure per-site policy as +described below. + +The smtp_tls_per_site table uses a simple "name whitespace value" format. +Specify host names or next-hop destinations on the left-hand side; no wildcards +are allowed. On the right hand side specify one of the following keywords: NONE - Don't use TLS at all. + Don't use TLS at all. This overrides a less specific MMAAYY lookup result + from the alternate host or next-hop lookup key, and overrides the + global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername + settings. MAY - Try to use STARTTLS if offered, otherwise use the unencrypted - connection. + Try to use TLS if the server announces support, otherwise use the + unencrypted connection. This has less precedence than a more specific + result (including NNOONNEE) from the alternate host or next-hop lookup key, + and has less precedence than the more specific global "smtp_enforce_tls + = yes" or "smtp_tls_enforce_peername = yes". + MUST_NOPEERMATCH + Require TLS encryption, but do not require that the remote SMTP server + hostname matches the information in the remote SMTP server certificate, + or that the server certificate was issued by a trusted CA. This + overrides a less secure NNOONNEE or a less specific MMAAYY lookup result from + the alternate host or next-hop lookup key, and overrides the global + smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. MUST - Require usage of STARTTLS, require that the remote SMTP server hostname + Require TLS encryption, require that the remote SMTP server hostname matches the information in the remote SMTP server certificate, and require that the remote SMTP server certificate was issued by a trusted - CA. - MUST_NOPEERMATCH - Require usage of STARTTLS, but do not require that the remote SMTP - server hostname matches the information in the remote SMTP server - certificate, or that the server certificate was issued by a trusted CA. + CA. This overrides a less secure NNOONNEE and MMUUSSTT__NNOOPPEEEERRMMAATTCCHH or a less + specific MMAAYY lookup result from the alternate host or next-hop lookup + key, and overrides the global smtp_use_tls, smtp_enforce_tls and + smtp_tls_enforce_peername settings. -The actual TLS usage policy depends not only on whether the next-hop -destination or remote SMTP server hostname are found in the smtp_tls_per_site -table, but also on the smtp_enforce_tls setting: +The precedences between global (main.cf) and per-site TLS policies can be +summarized as follows: - * If no match was found, the policy is applied as specified with - smtp_enforce_tls. + * When neither the remote SMTP server hostname nor the next-hop destination + are found in the smtp_tls_per_site table, the policy is based on + smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername. Note: + "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" imply + "smtp_use_tls = yes". - * If a match was found, and the smtp_enforce_tls policy is "enforce", NONE - explicitly switches it off; otherwise the "enforce" mode is used even for - entries that specify MAY. + * When both hostname and next-hop destination lookups produce a result, the + more specific per-site policy (NONE, MUST, etc) overrides the less specific + one (MAY), and the more secure per-site policy (MUST, etc) overrides the + less secure one (NONE). -Special hint for TLS enforcement mode: since no secure DNS lookup mechanism is -available, mail can be delivered to the wrong remote SMTP server. This is not -prevented by specifying MUST for the next-hop domain name. The recommended -setup is: specify local transport(5) table entries for sensitive domains with -explicit smtp:[mailhost] destinations (since you can assure security of this -table unlike DNS), then specify MUST for these mail hosts in the -smtp_tls_per_site table. + * After the per-site policy lookups are combined, the result generally + overrides the global policy. The exception is the less specific MMAAYY per- + site policy, which is overruled by the more specific global + "smtp_enforce_tls = yes" with server certificate verification as specified + with the smtp_tls_enforce_peername parameter. + +CClloossiinngg aa DDNNSS lloooopphhoollee wwiitthh ppeerr--ssiittee TTLLSS ppoolliicciieess + +As long as no secure DNS lookup mechanism is available, false hostnames may +appear in MX or CNAME responses. Even with a perfect match between the server +hostname and the server certificate, there is no guarantee that Postfix is +connected to the right server. To avoid this loophole take the following steps: + + * Eliminate MX lookups. Specify local transport(5) table entries for + sensitive domains with explicit smtp:[mailhost] or smtp:[mailhost]:port + destinations (you can assure security of this table unlike DNS); in the + smtp_tls_per_site table specify the value MMUUSSTT for the key [mailhost] or + smtp:[mailhost]:port. This prevents false hostname information in DNS MX + records from changing the server hostname that Postfix uses for TLS policy + lookup and server certificate verification. + + * Disallow CNAME hostname overrides. In main.cf specify + "smtp_cname_overrides_servername = no". This prevents false hostname + information in DNS CNAME records from changing the server hostname that + Postfix uses for TLS policy lookup and server certificate verification. + This feature requires Postfix 2.2.9 or later. Example: /etc/postfix/main.cf: smtp_tls_per_site = hash:/etc/postfix/tls_per_site + relayhost = [msa.example.net]:587 + + /etc/postfix/tls_per_site: + # relayhost exact nexthop match + [msa.example.net]:587 MUST + + # example.org (as nexthop) has MX hosts with broken TLS. + example.org NONE + + # Except for (as host) mx1.example.org which works. + mx1.example.org MAY + +DDiissccoovveerriinngg sseerrvveerrss tthhaatt ssuuppppoorrtt TTLLSS As we decide on a "per site" basis whether or not to use TLS, it would be good to have a list of sites that offered "STARTTLS". We can collect it ourselves @@ -768,7 +836,7 @@ Example: /etc/postfix/main.cf: smtp_tls_note_starttls_offer = yes -SSeerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn +SSeerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn ddeepptthh When verifying a remote SMTP server certificate, a verification depth of 1 is sufficient if the certificate is directly issued by a CA specified with @@ -1017,10 +1085,25 @@ J and in order to access the TLS session cache databases. Such a protocol cannot be run across fifos. + * smtp_tls_per_site: the MUST_NOPEERMATCH per-site policy cannot override the + global "smtp_tls_enforce_peername = yes" setting. + + * smtp_tls_per_site: a combined (NONE + MAY) lookup result for (hostname and + next-hop destination) produces counter-intuitive results for different + main.cf settings. TLS is enabled with "smtp_tls_enforce_peername = no", but + it is disabled when both "smtp_enforce_tls = yes" and + "smtp_tls_enforce_peername = yes". + +The smtp_tls_per_site limitations were removed by the end of the Postfix 2.2 +support cycle. + CCrreeddiittss * TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus Technical University. * Wietse Venema adopted the code, did some restructuring, and compiled this part of the documentation from Lutz's documents. + * Victor Duchovni was instrumental with the re-implementation of the + smtp_tls_per_site code in terms of enforcement levels, which simplified the + implementation greatly. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 96233b96b..4dde0c609 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -17,6 +17,48 @@ Incompatibility with Postfix 2.1 and earlier If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2 before proceeding. +Incompatibility with snapshot 20060123 +====================================== + +Postfix now preserves uppercase information while mapping addresses +with canonical, virtual, relocated or generic maps; this happens +even with lookups from regular expression maps. However, the local(8) +and virtual(8) delivery agents still fold addresses to lower case. + +By default, Postfix now folds the search string to lowercase only +with tables that have fixed-case lookup fields such as btree:, +hash:, dbm:, ldap:, or *sql:. The search string is no longer case +folded with tables whose lookup fields can match both upper or lower +case, such as regexp:, pcre:, or cidr:. + +For safety reasons, Postfix no longer allows $number substitution +in regexp: or pcre: transport tables or per-sender relayhost tables. + +For safety reasons, daemons that don't need privileges now insist +that they are configured as unprivileged in master.cf. + +Major changes with snapshot 20060123 +==================================== + +Postfix now does a better job at preserving upper/lower case +information while transforming addresses. The table lookup code +was revised, and is now more careful about when it folds search +strings to lower case. As a side effect, Postfix now also does a +better job at being case insensitive where it should, for example +while searching per-host TLS policies or SASL passwords. + +Some obscure behavior was eliminated from the smtp_tls_per_site +feature, without changes to the user interface. some Postfix internals +had to be re-structured in preparation for a more general TLS policy +mechanism; this required that smtp_tls_per_site be re-implemented +from scratch. + +Postfix 2.3 is expected to provide a new per-site TLS policy mechanism +that eliminates DNS spoofing attacks more effectively; the legacy +smtp_tls_per_site feature will be kept intact for a few releases +so that sites can upgrade Postfix without being forced to use a +different TLS policy mechanism. + Incompatibility with snapshot 20060112 ====================================== @@ -28,7 +70,7 @@ and mail will not be delivered. The Postfix SMTP/LMTP client by default no longer allows DNS CNAME records to override the server hostname that is used for logging, SASL password lookup, TLS policy selection and TLS server certificate -verification. Specify "smtp_cname_overrides_servername = no" to get +verification. Specify "smtp_cname_overrides_servername = yes" to get the old behavior. Postfix DSN reports no longer make up their own surrogate SMTP diff --git a/postfix/html/CDB_README.html b/postfix/html/CDB_README.html index 4307cc6f7..9d81ee2f7 100644 --- a/postfix/html/CDB_README.html +++ b/postfix/html/CDB_README.html @@ -54,7 +54,7 @@ available from http://www.corpit

Tinycdb is preferred, since it is a bit faster, has additional useful functionality and is much simpler to use.

-

To build Postfix after you have installed CDB, use something +

To build Postfix after you have installed tinycdb, use something like:

@@ -65,7 +65,11 @@ like:

"AUXLIBS=$CDB/libcdb.a" % make -for tinycdb, or alternatively, for the D.J.B. version:
+
+ +

Alternatively, for the D.J.B. version of CDB:

+ +

 % make tidy
 % CDB=../../../cdb-0.75
diff --git a/postfix/html/OVERVIEW.html b/postfix/html/OVERVIEW.html
index 84cbd7f21..9bdf973e6 100644
--- a/postfix/html/OVERVIEW.html
+++ b/postfix/html/OVERVIEW.html
@@ -411,7 +411,7 @@ responsible for starting Postfix server processes to receive and
 deliver mail, and for restarting servers that terminate prematurely
 because of some problem. The master(8) server is also responsible
 for enforcing the server process count limits as specified in the
-master.cf configuration file. The picture below gives the
+master.cf configuration file. The picture below gives the
 program hierarchy when Postfix is started up. Only some of the mail
 handling daemon processes are shown. 

@@ -687,7 +687,7 @@ queue files. This is a limited, preliminary utility. This program is likely to be superseded by something more powerful that can also edit Postfix queue files.

-
  • The postconf(1) command displays or updates Postfix main.cf +

  • The postconf(1) command displays or updates Postfix main.cf parameters and displays system dependent information about the supported file locking methods, and the supported types of lookup tables.

    diff --git a/postfix/html/SMTPD_POLICY_README.html b/postfix/html/SMTPD_POLICY_README.html index 869861c9b..179b22fc2 100644 --- a/postfix/html/SMTPD_POLICY_README.html +++ b/postfix/html/SMTPD_POLICY_README.html @@ -79,6 +79,7 @@ helo_name=some.domain.tld queue_id=8045F2AB23 sender=foo@bar.tld recipient=bar@foo.tld +recipient_count=0 client_address=1.2.3.4 client_name=another.domain.tld reverse_client_name=another.domain.tld @@ -115,8 +116,19 @@ encryption_keysize=256

  • When an attribute value is unavailable, the client - either does not send the attribute, or sends the attribute with - an empty value ("name=").

    + either does not send the attribute, sends the attribute with + an empty value ("name="), or sends a zero value ("name=0") in + the case of a numerical attribute.

    + +
  • The "recipient" attribute is available only in the + "RCPT TO" stage, and in the "DATA" and "END-OF-MESSAGE" stages + when Postfix accepted only one recipient for the current message. +

    + +
  • The "recipient_count" attribute (Postfix 2.3 and later) + is non-zero only in the "DATA" and "END-OF-MESSAGE" stages. It + specifies the number of recipients that Postfix accepted for + the current message.

  • The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6. @@ -217,11 +229,11 @@ daemon, you would use something like this:

    - 1 /etc/postfix/master.cf:
    + 1 /etc/postfix/master.cf:
      2     policy  unix  -       n       n       -       -       spawn
      3       user=nobody argv=/some/where/policy-server
      4 
    - 5 /etc/postfix/main.cf:
    + 5 /etc/postfix/main.cf:
      6     smtpd_recipient_restrictions =
      7         ... 
      8         reject_unauth_destination 
    @@ -239,8 +251,8 @@ daemon, you would use something like this: 

    its child process after 1000 seconds. This is too short for a policy daemon that may run for as long as an SMTP client is connected to an SMTP server process. The default time limit is overruled in -main.cf with an explicit "policy_time_limit" setting. The name of -the parameter is the name of the master.cf entry ("policy") +main.cf with an explicit "policy_time_limit" setting. The name of +the parameter is the name of the master.cf entry ("policy") concatenated with the "_time_limit" suffix.

  • Lines 8, 9: always specify "check_policy_service" AFTER @@ -254,11 +266,11 @@ TCP sockets instead:

    - 1 /etc/postfix/master.cf:
    + 1 /etc/postfix/master.cf:
      2     127.0.0.1:9998  inet  n       n       n       -       -       spawn
      3       user=nobody argv=/some/where/policy-server
      4 
    - 5 /etc/postfix/main.cf:
    + 5 /etc/postfix/main.cf:
      6     smtpd_recipient_restrictions =
      7         ... 
      8         reject_unauth_destination 
    @@ -320,7 +332,7 @@ $greylist_delay=60;
     
     

    The /var/mta directory (or whatever you choose) should be writable by "nobody", or by whatever username you configure below -in master.cf for the policy service.

    +in master.cf for the policy service.

    Example:

    @@ -346,11 +358,11 @@ processes only:

    -1 /etc/postfix/master.cf:
    +1 /etc/postfix/master.cf:
     2     policy  unix  -       n       n       -       -       spawn
     3       user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl
     4 
    -5 /etc/postfix/main.cf:
    +5 /etc/postfix/main.cf:
     6      policy_time_limit = 3600
     
    @@ -366,8 +378,8 @@ each request and reply.

    its child process after 1000 seconds. This is too short for a policy daemon that may run for as long as an SMTP client is connected to an SMTP server process. The default time limit is overruled in -main.cf with an explicit "policy_time_limit" setting. The name of -the parameter is the name of the master.cf entry ("policy") +main.cf with an explicit "policy_time_limit" setting. The name of +the parameter is the name of the master.cf entry ("policy") concatenated with the "_time_limit" suffix.

    @@ -378,11 +390,11 @@ client/server configuration" section above.

    -1 /etc/postfix/master.cf:
    +1 /etc/postfix/master.cf:
     2     127.0.0.1:9998  inet  n       n       n       -       -       spawn
     3       user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl
     4 
    -5 /etc/postfix/main.cf:
    +5 /etc/postfix/main.cf:
     6      127.0.0.1:9998_time_limit = 3600
     
    @@ -400,7 +412,7 @@ forged MAIL FROM domains could be found at
    - 1 /etc/postfix/main.cf:
    + 1 /etc/postfix/main.cf:
      2     smtpd_recipient_restrictions =
      3         reject_unlisted_recipient
      4         ...
    @@ -450,7 +462,7 @@ database relatively quickly. 

    - 1 /etc/postfix/main.cf:
    + 1 /etc/postfix/main.cf:
      2     smtpd_recipient_restrictions =
      3         reject_unlisted_recipient
      4         ...
    diff --git a/postfix/html/TLS_README.html b/postfix/html/TLS_README.html
    index 0ff0d03f2..29d77edff 100644
    --- a/postfix/html/TLS_README.html
    +++ b/postfix/html/TLS_README.html
    @@ -129,6 +129,11 @@ the make(1) files with the necessary definitions. This is
     done by invoking the command "make makefiles" in the Postfix
     top-level directory and with arguments as shown next. 

    +

    NOTE: Do not use Gnu TLS. It will spontaneously terminate +a process with exit status code 2, instead of properly reporting +problems to Postfix, so that it can log them to the maillog file. +

    +
    • If the OpenSSL include files (such as ssl.h) are @@ -274,7 +279,7 @@ is correctly configured to supply its intermediate CA certificate).

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_cert_file = /etc/postfix/server.pem
           smtpd_tls_key_file = $smtpd_tls_cert_file
       
      @@ -284,7 +289,7 @@ is correctly configured to supply its intermediate CA certificate).

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
           smtpd_tls_dkey_file = $smtpd_tls_dcert_file
       
      @@ -334,7 +339,7 @@ the TLS handshake when client certificates are requested.

      Example:

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_CAfile = /etc/postfix/CAcert.pem
           smtpd_tls_CApath = /etc/postfix/certs
       
      @@ -376,7 +381,7 @@ strongly discouraged.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_loglevel = 0
       
      @@ -392,7 +397,7 @@ since the headers may be changed by intermediate servers.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_received_header = yes
       
      @@ -407,7 +412,7 @@ using "smtpd_use_tls = yes".

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_use_tls = yes
       
      @@ -430,7 +435,7 @@ This option is off by default and should only seldom be used.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_enforce_tls = yes
       
      @@ -442,8 +447,8 @@ Outlook [Express] prefer the "wrapper" mode. This is true for OE (Win32 < 5.0 and Win32 >=5.0 when run on a port<>25 and OE (5.01 Mac on all ports).

      -

      It is strictly discouraged to use this mode from main.cf. If -you want to support this service, enable a special port in master.cf +

      It is strictly discouraged to use this mode from main.cf. If +you want to support this service, enable a special port in master.cf and specify "-o smtpd_tls_wrappermode = yes" as an smtpd(8) command line option. Port 465 (smtps) was once chosen for this feature.

      @@ -452,7 +457,7 @@ line option. Port 465 (smtps) was once chosen for this feature.
      -/etc/postfix/master.cf:
      +/etc/postfix/master.cf:
           smtps    inet  n       -       n       -       -       smtpd
             -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
       
      @@ -477,7 +482,7 @@ feature.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_ask_ccert = no
       
      @@ -500,7 +505,7 @@ logged.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_req_ccert = no
       
      @@ -515,7 +520,7 @@ CA issues special CA which then issues the actual certificate...)
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_ccert_verifydepth = 5
       
      @@ -536,7 +541,7 @@ set "smtpd_tls_auth_only = yes
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_auth_only = no
       
      @@ -560,7 +565,7 @@ the cost of repeatedly negotiating TLS session keys is high.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
       
      @@ -574,7 +579,7 @@ recommends a maximum of 24 hours.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_session_cache_timeout = 3600s
       
      @@ -622,7 +627,7 @@ certificate must no longer be used (e.g. an employee leaving).

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_recipient_restrictions = 
               ... 
               permit_tls_clientcerts 
      @@ -643,7 +648,7 @@ the user or host.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           relay_clientcerts = hash:/etc/postfix/relay_clientcerts
       
       /etc/postfix/relay_clientcerts:
      @@ -665,7 +670,7 @@ don't know what to do with it, simply don't touch it and leave the
        
       
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_cipherlist = DEFAULT
       
      @@ -691,7 +696,7 @@ those distributed with other TLS packages.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
           smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
       
      @@ -707,7 +712,7 @@ handshake procedures.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtpd_starttls_timeout = 300s
       
      @@ -726,9 +731,23 @@ key configuration
    • Client-side TLS session cache -
    • Enabling TLS in the Postfix SMTP client +
    • Enabling TLS in the Postfix SMTP client -
    • Server certificate verification +
    • Requiring TLS encryption + +
    • Disabling server certificate verification + +
    • Per-site TLS policies + + + +
    • Closing a DNS loophole with per-site TLS policies + +
    • Discovering servers that support TLS + +
    • Server certificate verification depth
    • Client-side cipher controls @@ -788,7 +807,7 @@ the overhead of the TLS exchange.

      certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. When you configure trust in a root CA, it is not necessary to explicitly trust -intermediary CAs signed by the root CA, unless $smtp_tls_verify_depth +intermediary CAs signed by the root CA, unless $smtp_tls_scert_verifydepth is less than the number of CAs in the certificate chain for the servers of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to @@ -800,7 +819,7 @@ is correctly configured to supply its intermediate CA certificate).

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_cert_file = /etc/postfix/client.pem
           smtp_tls_key_file = $smtp_tls_cert_file
       
      @@ -810,7 +829,7 @@ is correctly configured to supply its intermediate CA certificate).

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_dcert_file = /etc/postfix/client-dsa.pem
           smtp_tls_dkey_file = $smtpd_tls_cert_file
       
      @@ -849,7 +868,7 @@ when the certificate is needed.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_CAfile = /etc/postfix/CAcert.pem
           smtp_tls_CApath = /etc/postfix/certs
       
      @@ -888,7 +907,7 @@ transmission after STARTTLS
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_loglevel = 0
       
      @@ -915,7 +934,7 @@ is allowed to negotiate per unit time.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_session_cache_database = btree:/etc/postfix/smtp_scache
       
      @@ -929,39 +948,37 @@ recommends a maximum of 24 hours.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_session_cache_timeout = 3600s
       
      -

      Enabling TLS in the Postfix SMTP client -

      +

      Enabling TLS in the Postfix SMTP +client

      By default, TLS is disabled in the Postfix SMTP client, so no difference to plain Postfix is visible. If you enable TLS, the Postfix SMTP client will send STARTTLS when TLS support is announced by the remote SMTP server.

      -

      WARNING: MS Exchange servers will announce STARTTLS support -even when the service is not configured, so that the TLS handshake -will fail. It may be wise to not use this option on your central -mail hub, as you don't know in advance whether you are going to -connect to such a host. Instead, use the smtp_tls_per_site -recipient/site specific options that are described below.

      - -

      When the TLS handshake fails and no other server is available, -the Postfix SMTP client defers the delivery attempt, and the mail -stays in the queue.

      +

      When the server accepts the STARTTLS command, but the subsequent +TLS handshake fails, and no other server is available, the Postfix SMTP +client defers the delivery attempt, and the mail stays in the queue. After +a handshake failure, the communications channel is in an indeterminate +state and cannot be used for non-TLS deliveries.

      Example:

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_use_tls = yes
       
      +

      Requiring TLS encryption +

      +

      You can ENFORCE the use of TLS, so that the Postfix SMTP client will not deliver mail over unencrypted connections. In this mode, the remote SMTP server hostname must match the information in the @@ -971,14 +988,14 @@ server certificate doesn't verify or the remote SMTP server hostname doesn't match, and no other server is available, the delivery attempt is deferred and the mail stays in the queue.

      -

      The remote SMTP server hostname used in the check is beyond -question, as it must be the principal hostname (no CNAME allowed -here). Checks are performed against all names provided as dNSNames +

      The remote SMTP server hostname is verified against all names +provided as dNSNames in the SubjectAlternativeName. If no dNSNames are specified, the -CommonName is checked. The behavior may be changed with the +CommonName is checked. Verification may be turned off with the smtp_tls_enforce_peername option which is discussed below.

      -

      This option is useful only if you know that you will only +

      Enforcing the use of TLS is useful if you know that you will +only connect to servers that support RFC 2487 _and_ that present server certificates that meet the above requirements. An example would be a client only sends email to one specific mailhub that offers @@ -988,11 +1005,14 @@ the necessary STARTTLS support.

      -/etc/postfix/main.cf:
      -    smtp_enforce_tls = no
      +/etc/postfix/main.cf:
      +    smtp_enforce_tls = yes
       
      +

      Disabling server certificate +verification

      +

      As of RFC 2487 the requirements for hostname checking for MTA clients are not set. When TLS is required (smtp_enforce_tls = yes), the option smtp_tls_enforce_peername can be set to "no" to disable @@ -1000,106 +1020,198 @@ strict remote SMTP server hostname checking. In this case, the mail delivery will proceed regardless of the CommonName etc. listed in the certificate.

      -

      Note: the smtp_tls_enforce_peername setting has no effect on -sessions that are controlled via the smtp_tls_per_site table.

      - -

      Disabling the remote SMTP server hostname verification can -make sense in closed environment where special CAs are created. -If not used carefully, this option opens the danger of a -"man-in-the-middle" attack (the CommonName of this possible attacker -is logged).

      +

      Despite the potential for eliminating "man-in-the-middle" and +other attacks, mandatory certificate/peername verification is not +viable as a default Internet mail delivery policy at this time. A +significant fraction of TLS enabled MTAs uses self-signed certificates, +or certificates that are signed by a private certificate authority. +On a machine that delivers mail to the Internet, if you set +smtp_enforce_tls = yes, you should probably also set +smtp_tls_enforce_peername = no. You can use the per-site TLS +policies (see below) to enable full peer verification for specific +destinations that are known to have verifiable TLS server certificates. +

      Example:

      -/etc/postfix/main.cf:
      -    smtp_tls_enforce_peername = yes
      +/etc/postfix/main.cf:
      +    smtp_enforce_tls = yes
      +    smtp_tls_enforce_peername = no
       
      -

      Generally, trying TLS can be a bad idea, as some servers offer -STARTTLS but the negotiation will fail leading to unexplainable -failures. Instead, it may be a good idea to choose the TLS usage -policy based on the recipient or the mailhub to which you are -connecting.

      +

      Per-site TLS policies

      -

      Deciding the TLS usage policy per recipient may be difficult, -since a single email delivery attempt can involve several recipients. -Instead, use of TLS is controlled by the Postfix next-hop destination -domain name and by the remote SMTP server hostname. If either of these -matches an entry in the smtp_tls_per_site table, appropriate action -is taken.

      +

      A small fraction of servers offer STARTTLS but the negotiation +consistently fails, leading to mail aging out of the queue and +bouncing back to the sender. In such cases, you can use the per-site +policies to disable TLS for the problem sites. Alternatively, you +can enable TLS for just a few specific sites and not enable it for +all sites.

      -

      The remote SMTP server hostname is simply the DNS name of the -server that the Postfix SMTP client connects to. The next-hop -destination is Postfix specific. By default, this is the domain -name in the recipient address, but this information can be overruled -by the transport(5) table or by the relayhost parameter setting. -In these cases the relayhost etc. must be listed in the smtp_tls_per_site -table, instead of the recipient domain name.

      + + +

      The smtp_tls_per_site table is searched for a policy that matches +the following information:

      -
      NONE
      Don't use TLS at all.
      +
      remote SMTP server hostname
      This is simply the DNS +name of the server that the Postfix SMTP client connects to; this +name may be obtained from other DNS lookups, such as MX lookups or +CNAME lookups.
      -
      MAY
      Try to use STARTTLS if offered, otherwise use -the unencrypted connection.
      - -
      MUST
      Require usage of STARTTLS, require that the -remote SMTP server hostname matches the information in the remote -SMTP server certificate, and require that the remote SMTP server -certificate was issued by a trusted CA.
      - -
      MUST_NOPEERMATCH
      Require usage of STARTTLS, but do -not require that the remote SMTP server hostname matches the -information in the remote SMTP server certificate, or that the -server certificate was issued by a trusted CA.
      +
      next-hop destination
      This is normally the domain +portion of the recipient address, but it may be overruled by +information from the transport(5) table, from the relayhost parameter +setting, or from the relay_transport setting. When it's not the +recipient domain, the next-hop destination can have the Postfix-specific +form "[name]", [name]:port", "name" or +"name:port".
      -

      The actual TLS usage policy depends not only on whether the -next-hop destination or remote SMTP server hostname are found in -the smtp_tls_per_site table, but also on the smtp_enforce_tls -setting:

      +

      When both the hostname lookup and the next-hop lookup succeed, +the host policy does not automatically override the next-hop policy. +Instead, precedence is given to either the more specific or the +more secure per-site policy as described below.

      + +

      The smtp_tls_per_site table uses a simple "name whitespace +value" format. Specify host names or next-hop destinations on +the left-hand side; no wildcards are allowed. On the right hand +side specify one of the following keywords:

      + +
      + +
      + +
      NONE
      Don't use TLS at all. This overrides a less +specific MAY lookup result from the alternate host or next-hop +lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, +and smtp_tls_enforce_peername settings.
      + +
      MAY
      Try to use TLS if the server announces support, +otherwise use the unencrypted connection. This has less precedence +than a more specific result (including NONE) from the alternate +host or next-hop lookup key, and has less precedence than the more +specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername += yes".
      + +
      MUST_NOPEERMATCH
      Require TLS encryption, but do not +require that the remote SMTP server hostname matches the information +in the remote SMTP server certificate, or that the server certificate +was issued by a trusted CA. This overrides a less secure NONE +or a less specific MAY lookup result from the alternate host +or next-hop lookup key, and overrides the global smtp_use_tls, +smtp_enforce_tls and smtp_tls_enforce_peername settings.
      + +
      MUST
      Require TLS encryption, require that the remote +SMTP server hostname matches the information in the remote SMTP +server certificate, and require that the remote SMTP server certificate +was issued by a trusted CA. This overrides a less secure NONE +and MUST_NOPEERMATCH or a less specific MAY lookup +result from the alternate host or next-hop lookup key, and overrides +the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername +settings.
      + +
      + +
      + +

      The precedences between global (main.cf) and per-site TLS +policies can be summarized as follows:

        -
      • If no match was found, the policy is applied as specified -with smtp_enforce_tls.

        +
      • When neither the remote SMTP server hostname nor the +next-hop destination are found in the smtp_tls_per_site table, the +policy is based on smtp_use_tls, smtp_enforce_tls and +smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and +"smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes".

        -
      • If a match was found, and the smtp_enforce_tls policy is -"enforce", NONE explicitly switches it off; otherwise the "enforce" -mode is used even for entries that specify MAY.

        +
      • When both hostname and next-hop destination lookups produce +a result, the more specific per-site policy (NONE, MUST, etc) +overrides the less specific one (MAY), and the more secure per-site +policy (MUST, etc) overrides the less secure one (NONE).

        + +
      • After the per-site policy lookups are combined, the result +generally overrides the global policy. The exception is the less +specific MAY per-site policy, which is overruled by the more +specific global "smtp_enforce_tls = yes" with server certificate +verification as specified with the smtp_tls_enforce_peername +parameter.

      -

      Special hint for TLS enforcement mode: since no secure DNS -lookup mechanism is available, mail can be delivered to the wrong -remote SMTP server. This is not prevented by specifying MUST for -the next-hop domain name. The recommended setup is: specify local -transport(5) table entries for sensitive domains with explicit -smtp:[mailhost] destinations (since you can assure security of this -table unlike DNS), then specify MUST for these mail hosts in the -smtp_tls_per_site table.

      +

      Closing a DNS loophole with + per-site TLS policies

      + +

      As long as no secure DNS lookup mechanism is available, false +hostnames may appear in MX or CNAME responses. Even with a perfect +match between the server hostname and the server certificate, there +is no guarantee that Postfix is connected to the right server. To +avoid this loophole take the following steps:

      + +
        + +
      • Eliminate MX lookups. Specify local transport(5) table +entries for sensitive domains with explicit smtp:[mailhost] +or smtp:[mailhost]:port destinations (you can assure +security of this table unlike DNS); in the smtp_tls_per_site table +specify the value MUST for the key [mailhost] or +smtp:[mailhost]:port. This prevents false hostname +information in DNS MX records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification.

        + +
      • Disallow CNAME hostname overrides. In main.cf specify +"smtp_cname_overrides_servername = no". This prevents false hostname +information in DNS CNAME records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. This feature requires Postfix 2.2.9 or later.

        + +

      Example:

      - -
      -
      -/etc/postfix/main.cf:
      +
      +
      +/etc/postfix/main.cf:
           smtp_tls_per_site = hash:/etc/postfix/tls_per_site
      +    relayhost = [msa.example.net]:587
      +
      +/etc/postfix/tls_per_site:
      +    # relayhost exact nexthop match
      +    [msa.example.net]:587       MUST
      +
      +    # example.org (as nexthop) has MX hosts with broken TLS.
      +    example.org                 NONE
      +
      +    # Except for (as host) mx1.example.org which works.
      +    mx1.example.org             MAY
       
      +

      Discovering servers that support +TLS

      +

      As we decide on a "per site" basis whether or not to use TLS, it would be good to have a list of sites that offered "STARTTLS". We can collect it ourselves with this option.

      @@ -1118,12 +1230,12 @@ postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_note_starttls_offer = yes
       
      -

      Server certificate verification

      +

      Server certificate verification depth

      When verifying a remote SMTP server certificate, a verification depth of 1 is sufficient if the certificate is directly issued by @@ -1135,7 +1247,7 @@ special CA which then issues the actual certificate...)

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_scert_verifydepth = 5
       
      @@ -1154,7 +1266,7 @@ don't know what to do with it, simply don't touch it and leave the
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_tls_cipherlist = DEFAULT
       
      @@ -1171,7 +1283,7 @@ defers delivery if no alternative server is available.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           smtp_starttls_timeout = 300s
       
      @@ -1191,7 +1303,7 @@ session key.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           tls_daemon_random_bytes = 32
       
      @@ -1206,11 +1318,11 @@ regular file, you must prepend the source type to the source name: "dev:" for a device special file, or "egd:" for a source with EGD compatible socket interface.

      -

      Examples (specify only one in main.cf):

      +

      Examples (specify only one in main.cf):

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           tls_random_source = dev:/dev/urandom
           tls_random_source = egd:/var/run/egd-pool
       
      @@ -1227,7 +1339,7 @@ entropy source, a larger amount of data can be read.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           tls_random_bytes = 32
       
      @@ -1242,7 +1354,7 @@ The default maximal time interval is 1 hour.

      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           tls_random_reseed_period = 3600s
       
      @@ -1260,7 +1372,7 @@ the file location should probably be on the /var partition (but
      -/etc/postfix/main.cf:
      +/etc/postfix/main.cf:
           tls_random_exchange_name = /etc/postfix/prng_exch
           tls_random_prng_update_period = 3600s
       
      @@ -1380,7 +1492,7 @@ super-user privileges.

    • Configure Postfix, by adding the following to -/etc/postfix/main.cf.

      +/etc/postfix/main.cf .

      @@ -1424,7 +1536,7 @@ patch by Lutz Jänicke, but differs in a few minor ways. 

        -
      • main.cf: Specify "btree" instead of "sdbm" for TLS +

      • main.cf: Specify "btree" instead of "sdbm" for TLS session cache databases.

        TLS session cache databases are now accessed only by the @@ -1439,7 +1551,7 @@ In most cases, btree databases should be adequate.

        NOTE: You cannot use dbm databases. TLS session objects are too large.

        -
      • master.cf: Specify "unix" instead of "fifo" as +

      • master.cf: Specify "unix" instead of "fifo" as the tlsmgr service type.

        The smtp(8) and smtpd(8) processes now use a client-server @@ -1447,8 +1559,22 @@ protocol in order to access the tlsmgr(8) pseudo-ran generation (PRNG) pool, and in order to access the TLS session cache databases. Such a protocol cannot be run across fifos.

        +
      • smtp_tls_per_site: the MUST_NOPEERMATCH per-site policy +cannot override the global "smtp_tls_enforce_peername = yes" setting. +

        + +
      • smtp_tls_per_site: a combined (NONE + MAY) lookup result +for (hostname and next-hop destination) produces counter-intuitive +results for different main.cf settings. TLS is enabled with +"smtp_tls_enforce_peername = no", but it is disabled when both +"smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes". +

        +
      +

      The smtp_tls_per_site limitations were removed by the end of +the Postfix 2.2 support cycle.

      +

      Credits

        @@ -1459,6 +1585,10 @@ Jänicke at Cottbus Technical University.
      • Wietse Venema adopted the code, did some restructuring, and compiled this part of the documentation from Lutz's documents. +
      • Victor Duchovni was instrumental with the re-implementation +of the smtp_tls_per_site code in terms of enforcement levels, which +simplified the implementation greatly. +
      diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index a5f60db28..6d744f593 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -69,7 +69,7 @@ CLEANUP(8) CLEANUP(8) then else and other logical relationships. CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically, as + Changes to main.cf are picked up automatically, as cleanup(8) processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. @@ -90,45 +90,46 @@ CLEANUP(8) CLEANUP(8) Report mail delivery errors to the address speci- fied with the non-standard Errors-To: message header, instead of the envelope sender address - (this feature is removed with Postfix 2.2, is - turned off by default with Postfix 2.1, and is - always turned on with older Postfix versions). + (this feature is removed with Postfix version 2.2, + is turned off by default with Postfix version 2.1, + and is always turned on with older Postfix ver- + sions). BUILT-IN CONTENT FILTERING CONTROLS - Postfix built-in content filtering is meant to stop a - flood of worms or viruses. It is not a general content + Postfix built-in content filtering is meant to stop a + flood of worms or viruses. It is not a general content filter. body_checks (empty) - Optional lookup tables for content inspection as + Optional lookup tables for content inspection as specified in the body_checks(5) manual page. header_checks (empty) - Optional lookup tables for content inspection of - primary non-MIME message headers, as specified in + Optional lookup tables for content inspection of + primary non-MIME message headers, as specified in the header_checks(5) manual page. Available in Postfix version 2.0 and later: body_checks_size_limit (51200) How much text in a message body segment (or attach- - ment, if you prefer to use that term) is subjected + ment, if you prefer to use that term) is subjected to body_checks inspection. mime_header_checks ($header_checks) - Optional lookup tables for content inspection of - MIME related message headers, as described in the + Optional lookup tables for content inspection of + MIME related message headers, as described in the header_checks(5) manual page. nested_header_checks ($header_checks) - Optional lookup tables for content inspection of - non-MIME message headers in attached messages, as + Optional lookup tables for content inspection of + non-MIME message headers in attached messages, as described in the header_checks(5) manual page. Available in Postfix version 2.3 and later: message_reject_characters (empty) - The set of characters that Postfix will reject in + The set of characters that Postfix will reject in message content. message_strip_characters (empty) @@ -150,19 +151,19 @@ CLEANUP(8) CLEANUP(8) will handle. strict_8bitmime (no) - Enable both strict_7bit_headers and strict_8bit- + Enable both strict_7bit_headers and strict_8bit- mime_body. strict_7bit_headers (no) Reject mail with 8-bit text in message headers. strict_8bitmime_body (no) - Reject 8-bit message body text without 8-bit MIME + Reject 8-bit message body text without 8-bit MIME content encoding information. strict_mime_encoding_domain (no) Reject mail with invalid Content-Transfer-Encoding: - information for the message/* or multipart/* MIME + information for the message/* or multipart/* MIME content types. AUTOMATIC BCC RECIPIENT CONTROLS @@ -170,31 +171,31 @@ CLEANUP(8) CLEANUP(8) mail enters the mail system: always_bcc (empty) - Optional address that receives a "blind carbon + Optional address that receives a "blind carbon copy" of each message that is received by the Post- fix mail system. Available in Postfix version 2.1 and later: sender_bcc_maps (empty) - Optional BCC (blind carbon-copy) address lookup + Optional BCC (blind carbon-copy) address lookup tables, indexed by sender address. recipient_bcc_maps (empty) - Optional BCC (blind carbon-copy) address lookup + Optional BCC (blind carbon-copy) address lookup tables, indexed by recipient address. ADDRESS TRANSFORMATION CONTROLS - Address rewriting is delegated to the trivial-rewrite(8) - daemon. The cleanup(8) server implements table driven + Address rewriting is delegated to the trivial-rewrite(8) + daemon. The cleanup(8) server implements table driven address mapping. empty_address_recipient (MAILER-DAEMON) - The recipient of mail addressed to the null + The recipient of mail addressed to the null address. canonical_maps (empty) - Optional address mapping lookup tables for message + Optional address mapping lookup tables for message headers and envelopes. recipient_canonical_maps (empty) @@ -205,49 +206,49 @@ CLEANUP(8) CLEANUP(8) Optional address mapping lookup tables for envelope and header sender addresses. - masquerade_classes (envelope_sender, header_sender, + masquerade_classes (envelope_sender, header_sender, header_recipient) What addresses are subject to address masquerading. masquerade_domains (empty) - Optional list of domains whose subdomain structure + Optional list of domains whose subdomain structure will be stripped off in email addresses. masquerade_exceptions (empty) - Optional list of user names that are not subjected - to address masquerading, even when their address + Optional list of user names that are not subjected + to address masquerading, even when their address matches $masquerade_domains. propagate_unmatched_extensions (canonical, virtual) - What address lookup tables copy an address exten- + What address lookup tables copy an address exten- sion from the lookup key to the lookup result. Available before Postfix version 2.0: virtual_maps (empty) Optional lookup tables with a) names of domains for - which all addresses are aliased to addresses in - other local or remote domains, and b) addresses - that are aliased to addresses in other local or + which all addresses are aliased to addresses in + other local or remote domains, and b) addresses + that are aliased to addresses in other local or remote domains. Available in Postfix version 2.0 and later: virtual_alias_maps ($virtual_maps) - Optional lookup tables that alias specific mail - addresses or domains to other local or remote + Optional lookup tables that alias specific mail + addresses or domains to other local or remote address. Available in Postfix version 2.2 and later: - canonical_classes (envelope_sender, envelope_recipient, + canonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient) - What addresses are subject to canonical_maps + What addresses are subject to canonical_maps address mapping. recipient_canonical_classes (envelope_recipient, header_recipient) - What addresses are subject to recipient_canoni- + What addresses are subject to recipient_canoni- cal_maps address mapping. sender_canonical_classes (envelope_sender, header_sender) @@ -255,15 +256,15 @@ CLEANUP(8) CLEANUP(8) address mapping. remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients + Don't rewrite message headers from remote clients at all when this parameter is empty; otherwise, re- - write message headers and append the specified + write message headers and append the specified domain name to incomplete addresses. RESOURCE AND RATE CONTROLS duplicate_filter_limit (1000) - The maximal number of addresses remembered by the - address duplicate filter for aliases(5) or vir- + The maximal number of addresses remembered by the + address duplicate filter for aliases(5) or vir- tual(5) alias expansion, or for showq(8) queue dis- plays. @@ -272,16 +273,16 @@ CLEANUP(8) CLEANUP(8) message header. hopcount_limit (50) - The maximal number of Received: message headers + The maximal number of Received: message headers that is allowed in the primary message headers. in_flow_delay (1s) - Time to pause before accepting a new message, when + Time to pause before accepting a new message, when the message arrival rate exceeds the message deliv- ery rate. message_size_limit (10240000) - The maximal size in bytes of a message, including + The maximal size in bytes of a message, including envelope information. Available in Postfix version 2.0 and later: @@ -299,35 +300,35 @@ CLEANUP(8) CLEANUP(8) will handle. queue_file_attribute_count_limit (100) - The maximal number of (name=value) attributes that + The maximal number of (name=value) attributes that may be stored in a Postfix queue file. Available in Postfix version 2.1 and later: virtual_alias_expansion_limit (1000) - The maximal number of addresses that virtual alias + The maximal number of addresses that virtual alias expansion produces from each original recipient. virtual_alias_recursion_limit (1000) - The maximal nesting depth of virtual alias expan- + The maximal nesting depth of virtual alias expan- sion. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to - handle a request before it is terminated by a + How much time a Postfix daemon process may take to + handle a request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal + The maximal number of digits after the decimal point when logging sub-second delay values. delay_warning_time (0h) - The time after which the sender receives the mes- + The time after which the sender receives the mes- sage headers of mail that is still queued. ipc_timeout (3600s) @@ -335,12 +336,12 @@ CLEANUP(8) CLEANUP(8) over an internal communication channel. max_idle (100s) - The maximum amount of time that an idle Postfix - daemon process waits for the next service request + The maximum amount of time that an idle Postfix + daemon process waits for the next service request before exiting. max_use (100) - The maximal number of connection requests before a + The maximal number of connection requests before a Postfix daemon process terminates. myhostname (see 'postconf -d' output) @@ -348,19 +349,19 @@ CLEANUP(8) CLEANUP(8) myorigin ($myhostname) The domain name that locally-posted mail appears to - come from, and that locally posted mail is deliv- + come from, and that locally posted mail is deliv- ered to. process_id (read-only) - The process ID of a Postfix command or daemon + The process ID of a Postfix command or daemon process. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. queue_directory (see 'postconf -d' output) - The location of the Postfix top-level queue direc- + The location of the Postfix top-level queue direc- tory. soft_bounce (no) @@ -371,14 +372,14 @@ CLEANUP(8) CLEANUP(8) The syslog facility of Postfix logging. syslog_name (postfix) - The mail system name that is prepended to the - process name in syslog records, so that "smtpd" + The mail system name that is prepended to the + process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". Available in Postfix version 2.1 and later: enable_original_recipient (yes) - Enable support for the X-Original-To message + Enable support for the X-Original-To message header. FILES @@ -401,7 +402,7 @@ CLEANUP(8) CLEANUP(8) ADDRESS_REWRITING_README Postfix address manipulation LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/flush.8.html b/postfix/html/flush.8.html index 0bbb27705..5a81f4161 100644 --- a/postfix/html/flush.8.html +++ b/postfix/html/flush.8.html @@ -70,7 +70,7 @@ FLUSH(8) FLUSH(8) fore can accumulate outdated or redundant data. In order to maintain sanity, "refresh" must be executed periodi- cally. This can be automated with a suitable wakeup timer - setting in the master.cf configuration file. + setting in the master.cf configuration file. Upon receipt of a request to deliver mail for an eligible destination, the flush(8) server requests delivery of all @@ -81,7 +81,7 @@ FLUSH(8) FLUSH(8) in one domain. CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically as flush(8) + Changes to main.cf are picked up automatically as flush(8) processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. @@ -89,8 +89,8 @@ FLUSH(8) FLUSH(8) postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/pickup.8.html b/postfix/html/pickup.8.html index 70e8d8df6..d64cb5bf1 100644 --- a/postfix/html/pickup.8.html +++ b/postfix/html/pickup.8.html @@ -44,7 +44,7 @@ PICKUP(8) PICKUP(8) CONFIGURATION PARAMETERS As the pickup(8) daemon is a relatively long-running - process, up to an hour may pass before a main.cf change + process, up to an hour may pass before a main.cf change takes effect. Use the command "postfix reload" command to speed up a change. @@ -62,8 +62,8 @@ PICKUP(8) PICKUP(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/postalias.1.html b/postfix/html/postalias.1.html index 57ac66b8b..dab7e015a 100644 --- a/postfix/html/postalias.1.html +++ b/postfix/html/postalias.1.html @@ -32,130 +32,139 @@ POSTALIAS(1) POSTALIAS(1) The format of Postfix alias input files is described in aliases(5). + By default the lookup key is mapped to lowercase to make + the lookups case insensitive; as of Postfix 2.3 this case + folding happens only with tables whose lookup keys are + fixed-case strings such as btree:, dbm: or hash:. With + earlier versions, the lookup key is folded even with + tables where a lookup field can match both upper and lower + case text, such as regexp: and pcre:. This resulted in + loss of information with $number substitutions. + Options: -c config_dir - Read the main.cf configuration file in the named + Read the main.cf configuration file in the named directory instead of the default configuration directory. - -d key Search the specified maps for key and remove one - entry per map. The exit status is zero when the + -d key Search the specified maps for key and remove one + entry per map. The exit status is zero when the requested information was found. If a key value of - is specified, the program reads key values from the standard input stream. The exit - status is zero when at least one of the requested + status is zero when at least one of the requested keys was found. -f Do not fold the lookup key to lower case while cre- - ating or querying a map. + ating or querying a table. - -i Incremental mode. Read entries from standard input + -i Incremental mode. Read entries from standard input and do not truncate an existing database. By - default, postalias(1) creates a new database from + default, postalias(1) creates a new database from the entries in file_name. - -N Include the terminating null character that termi- - nates lookup keys and values. By default, postal- - ias(1) does whatever is the default for the host + -N Include the terminating null character that termi- + nates lookup keys and values. By default, postal- + ias(1) does whatever is the default for the host operating system. - -n Don't include the terminating null character that - terminates lookup keys and values. By default, - postalias(1) does whatever is the default for the + -n Don't include the terminating null character that + terminates lookup keys and values. By default, + postalias(1) does whatever is the default for the host operating system. - -o Do not release root privileges when processing a + -o Do not release root privileges when processing a non-root input file. By default, postalias(1) drops - root privileges and runs as the source file owner + root privileges and runs as the source file owner instead. -p Do not inherit the file access permissions from the input file when creating a new file. Instead, cre- - ate a new file with default access permissions + ate a new file with default access permissions (mode 0644). - -q key Search the specified maps for key and write the - first value found to the standard output stream. + -q key Search the specified maps for key and write the + first value found to the standard output stream. The exit status is zero when the requested informa- tion was found. If a key value of - is specified, the program reads - key values from the standard input stream and - writes one line of key: value output for each key - that was found. The exit status is zero when at + key values from the standard input stream and + writes one line of key: value output for each key + that was found. The exit status is zero when at least one of the requested keys was found. -r When updating a table, do not complain about attempts to update existing entries, and make those updates anyway. - -s Retrieve all database elements, and write one line + -s Retrieve all database elements, and write one line of key: value output for each element. The elements - are printed in database order, which is not neces- - sarily the same as the original input order. This - feature is available in Postfix version 2.2 and + are printed in database order, which is not neces- + sarily the same as the original input order. This + feature is available in Postfix version 2.2 and later, and is not available for all database types. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. -w When updating a table, do not complain about - attempts to update existing entries, and ignore + attempts to update existing entries, and ignore those attempts. Arguments: file_type - The database type. To find out what types are sup- + The database type. To find out what types are sup- ported, use the "postconf -m" command. - The postalias(1) command can query any supported - file type, but it can create only the following + The postalias(1) command can query any supported + file type, but it can create only the following file types: - btree The output is a btree file, named - file_name.db. This is available on systems - with support for db databases. - - cdb The output is one file named file_name.cdb. - This is available on systems with support - for cdb databases. - - dbm The output consists of two files, named - file_name.pag and file_name.dir. This is - available on systems with support for dbm - databases. - - hash The output is a hashed file, named + btree The output is a btree file, named file_name.db. This is available on systems with support for db databases. - sdbm The output consists of two files, named + cdb The output is one file named file_name.cdb. + This is available on systems with support + for cdb databases. + + dbm The output consists of two files, named file_name.pag and file_name.dir. This is - available on systems with support for sdbm + available on systems with support for dbm databases. - When no file_type is specified, the software uses - the database type specified via the default_data- + hash The output is a hashed file, named + file_name.db. This is available on systems + with support for db databases. + + sdbm The output consists of two files, named + file_name.pag and file_name.dir. This is + available on systems with support for sdbm + databases. + + When no file_type is specified, the software uses + the database type specified via the default_data- base_type configuration parameter. The default - value for this parameter depends on the host envi- + value for this parameter depends on the host envi- ronment. file_name - The name of the alias database source file when + The name of the alias database source file when creating a database. DIAGNOSTICS - Problems are logged to the standard error stream and to - syslogd(8). No output means that no problems were - detected. Duplicate entries are skipped and are flagged + Problems are logged to the standard error stream and to + syslogd(8). No output means that no problems were + detected. Duplicate entries are skipped and are flagged with a warning. - postalias(1) terminates with zero exit status in case of - success (including successful "postalias -q" lookup) and + postalias(1) terminates with zero exit status in case of + success (including successful "postalias -q" lookup) and terminates with non-zero exit status in case of failure. ENVIRONMENT @@ -166,26 +175,26 @@ POSTALIAS(1) POSTALIAS(1) Enable verbose logging for debugging purposes. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf 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 postconf(5) for more details including examples. alias_database (see 'postconf -d' output) - The alias databases for local(8) delivery that are + The alias databases for local(8) delivery that are updated with "newaliases" or with "sendmail -bi". config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. berkeley_db_create_buffer_size (16777216) - The per-table I/O buffer size for programs that + The per-table I/O buffer size for programs that create Berkeley DB hash or btree tables. berkeley_db_read_buffer_size (131072) - The per-table I/O buffer size for programs that + The per-table I/O buffer size for programs that read Berkeley DB hash or btree tables. default_database_type (see 'postconf -d' output) @@ -196,8 +205,8 @@ POSTALIAS(1) POSTALIAS(1) The syslog facility of Postfix logging. syslog_name (postfix) - The mail system name that is prepended to the - process name in syslog records, so that "smtpd" + The mail system name that is prepended to the + process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". STANDARDS @@ -216,7 +225,7 @@ POSTALIAS(1) POSTALIAS(1) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 6a8686f24..804da530c 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -1927,7 +1927,8 @@ Do not change this unless you have a complete understanding of defer(8) service. This service maintains a record +The name of the defer service. This service is implemented by the +bounce(8) daemon and maintains a record of failed delivery attempts and generates non-delivery notifications.

      @@ -5172,7 +5173,7 @@ This feature is available in Postfix 2.0 and later. -
      plaintext_session_reject_code +
      plaintext_reject_code (default: 450)

      @@ -7552,71 +7553,77 @@ postfix/smtp[pid]: Host offered STARTTLS: [name.of.host] (default: empty)

      Optional lookup tables with the Postfix SMTP client TLS usage -policy by next-hop domain name and by remote SMTP server hostname. -

      +policy by next-hop destination and by remote SMTP server hostname. +When both lookups succeed, the more specific per-site policy (NONE, +MUST, etc) overrides the less specific one (MAY), and the more +secure per-site policy (MUST, etc) overrides the less secure one +(NONE).

      -

      Table format: domain names or server hostnames are specified -on the left-hand side; no wildcards are allowed. On the right hand -side specify one of the following keywords:

      +

      Specify a next-hop destination or server hostname on the left-hand +side; no wildcards are allowed. The next-hop destination is either +the recipient domain, or the destination specified with a transport(5) +table, the relayhost parameter, or the relay_transport parameter. +On the right hand side specify one of the following keywords:

      -
      NONE
      Don't use TLS at all.
      +
      NONE
      Don't use TLS at all. This overrides a less +specific MAY lookup result from the alternate host or next-hop +lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, +and smtp_tls_enforce_peername settings.
      -
      MAY
      Try to use STARTTLS if offered, otherwise use -the unencrypted connection.
      +
      MAY
      Try to use TLS if the server announces support, +otherwise use the unencrypted connection. This has less precedence +than a more specific result (including NONE) from the alternate +host or next-hop lookup key, and has less precedence than the more +specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername += yes".
      -
      MUST
      Require usage of STARTTLS, require that the -remote SMTP server hostname matches the information in the remote -SMTP server certificate, and require that the remote SMTP server -certificate was issued by a trusted CA.
      +
      MUST_NOPEERMATCH
      Require TLS encryption, but do not +require that the remote SMTP server hostname matches the information +in the remote SMTP server certificate, or that the server certificate +was issued by a trusted CA. This overrides a less secure NONE +or a less specific MAY lookup result from the alternate host +or next-hop lookup key, and overrides the global smtp_use_tls, +smtp_enforce_tls and smtp_tls_enforce_peername settings.
      -
      MUST_NOPEERMATCH
      Require usage of STARTTLS, but do -not require that the remote SMTP server hostname matches the -information in the remote SMTP server certificate, or that the -server certificate was issued by a trusted CA.
      +
      MUST
      Require TLS encryption, require that the remote +SMTP server hostname matches the information in the remote SMTP +server certificate, and require that the remote SMTP server certificate +was issued by a trusted CA. This overrides a less secure NONE +and MUST_NOPEERMATCH or a less specific MAY lookup +result from the alternate host or next-hop lookup key, and overrides +the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername +settings.
      -

      Special hints for enforcement mode: since no secure DNS lookup -mechanism is available, the recommended setup is:

      +

      As long as no secure DNS lookup mechanism is available, false +hostnames in MX or CNAME responses can change the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. Even with a perfect match between the server hostname +and the server certificate, there is no guarantee that Postfix is +connected to the right server. To avoid this loophole take the +following steps:

      -
      +
        -
        Postfix 2.2.9
        +
      • Disallow CNAME hostname overrides. In main.cf specify +"smtp_cname_overrides_servername = no". This prevents false hostname +information in DNS CNAME records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. This feature requires Postfix 2.2.9 or later. -
          +
        • Eliminate MX lookups. Specify local transport(5) table entries +for sensitive domains with explicit smtp:[mailhost] or smtp:[mailhost]:port +destinations. This prevents false hostname information in DNS MX +records from changing the server hostname that Postfix uses for TLS +policy lookup and server certificate verification. -
        • Specify "smtp_cname_overrides_servername = no". This avoids -false hostname information in DNS CNAME records that could bypass -a hostname-based TLS usage policy. +
        • Specify MUST for these mail hosts (including [ ] and port) in +the smtp_tls_per_site table. -
        • Specify local transport(5) table entries for sensitive domains -with explicit smtp:[mailhost] destinations. This avoids false -hostname information in DNS MX records that could bypass a -hostname-based TLS usage policy. - -
        • Specify MUST for these mail hosts in the smtp_tls_per_site -table. - -
        - -
        Postfix < 2.2.9
        - -
          - -
        • Specify local transport(5) table entries for sensitive domains -with explicit smtp:[mailhost] destinations. This avoids false -hostname information in DNS MX records that could bypass a -hostname-based TLS usage policy, but cannot avoid false hostname -information in DNS CNAME records. - -
        • Specify MUST for these mail hosts in the smtp_tls_per_site -table. - -
        - -
      +

    @@ -8199,9 +8206,11 @@ a restriction list, to make the default policy explicit.
    reject_multi_recipient_bounce
    Reject the request when the envelope sender is the null address, -and the message has multiple envelope recipients. Although this -usage is technically allowed, it seems to have no legitimate -application.
    Note: this restriction can only work reliably +and the message has multiple envelope recipients. This usage has +rare but legitimate applications: under certain conditions, +multi-recipient mail that was posted with the DSN option NOTIFY=NEVER +may be forwarded with the null sender address. +
    Note: this restriction can only work reliably when used in smtpd_data_restrictions or smtpd_end_of_data_restrictions, because the total number of recipients is not known at an earlier stage of the SMTP conversation. @@ -8217,7 +8226,7 @@ is available in Postfix 2.1 and later.
    restriction should not be used before the client has had a chance to negotiate encryption with the AUTH or STARTTLS commands.
    -The plaintext_session_reject_code parameter specifies the response +The plaintext_reject_code parameter specifies the response code for rejected requests (default: 450). This feature is available in Postfix 2.3 and later. @@ -10283,7 +10292,8 @@ gives timeout errors.

    (default: trace)

    -The name of the trace(8) service. This service maintains a record +The name of the trace service. This service is implemented by the +bounce(8) daemon and maintains a record of mail deliveries and produces a mail delivery report when verbose delivery is requested with "sendmail -v".

    diff --git a/postfix/html/postdrop.1.html b/postfix/html/postdrop.1.html index 4510e9e20..5eec30834 100644 --- a/postfix/html/postdrop.1.html +++ b/postfix/html/postdrop.1.html @@ -19,7 +19,7 @@ POSTDROP(1) POSTDROP(1) Options: -c config_dir - The main.cf configuration file is in the named + The main.cf configuration file is in the named directory instead of the default configuration directory. See also the MAIL_CONFIG environment setting below. @@ -49,18 +49,18 @@ POSTDROP(1) POSTDROP(1) ENVIRONMENT MAIL_CONFIG - Directory with the main.cf file. In order to avoid + Directory with the main.cf file. In order to avoid exploitation of set-group ID privileges, a non- standard directory is allowed only if: - o The name is listed in the standard main.cf + o The name is listed in the standard main.cf file with the alternate_config_directories configuration parameter. o The command is invoked by the super-user. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. The text below provides only a parameter summary. See postconf(5) for more details including exam- ples. @@ -72,8 +72,8 @@ POSTDROP(1) POSTDROP(1) environment parameter. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. import_environment (see 'postconf -d' output) The list of environment parameters that a Postfix diff --git a/postfix/html/postmap.1.html b/postfix/html/postmap.1.html index ed2e90e75..53d86f0b3 100644 --- a/postfix/html/postmap.1.html +++ b/postfix/html/postmap.1.html @@ -49,12 +49,20 @@ POSTMAP(1) POSTMAP(1) rounding white space is stripped off. Unlike with Postfix alias databases, quotes cannot be used to protect lookup keys that contain special characters such as `#' or white- - space. The key is mapped to lowercase to make mapping - lookups case insensitive. + space. + + By default the lookup key is mapped to lowercase to make + the lookups case insensitive; as of Postfix 2.3 this case + folding happens only with tables whose lookup keys are + fixed-case strings such as btree:, dbm: or hash:. With + earlier versions, the lookup key is folded even with + tables where a lookup field can match both upper and lower + case text, such as regexp: and pcre:. This resulted in + loss of information with $number substitutions. COMMAND-LINE ARGUMENTS -c config_dir - Read the main.cf configuration file in the named + Read the main.cf configuration file in the named directory instead of the default configuration directory. @@ -68,7 +76,7 @@ POSTMAP(1) POSTMAP(1) keys was found. -f Do not fold the lookup key to lower case while cre- - ating or querying a map. + ating or querying a table. -i Incremental mode. Read entries from standard input and do not truncate an existing database. By @@ -183,7 +191,7 @@ POSTMAP(1) POSTMAP(1) Enable verbose logging for debugging purposes. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. The text below provides only a parameter summary. See postconf(5) for more details including exam- ples. @@ -197,8 +205,8 @@ POSTMAP(1) POSTMAP(1) read Berkeley DB hash or btree tables. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. default_database_type (see 'postconf -d' output) The default database type for use in newaliases(1), diff --git a/postfix/html/postqueue.1.html b/postfix/html/postqueue.1.html index 29a64ee79..b18850100 100644 --- a/postfix/html/postqueue.1.html +++ b/postfix/html/postqueue.1.html @@ -25,7 +25,7 @@ POSTQUEUE(1) POSTQUEUE(1) The following options are recognized: -c config_dir - The main.cf configuration file is in the named + The main.cf configuration file is in the named directory instead of the default configuration directory. See also the MAIL_CONFIG environment setting below. @@ -89,18 +89,18 @@ POSTQUEUE(1) POSTQUEUE(1) ENVIRONMENT MAIL_CONFIG - Directory with the main.cf file. In order to avoid + Directory with the main.cf file. In order to avoid exploitation of set-group ID privileges, a non- standard directory is allowed only if: - o The name is listed in the standard main.cf + o The name is listed in the standard main.cf file with the alternate_config_directories configuration parameter. o The command is invoked by the super-user. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. The text below provides only a parameter summary. See postconf(5) for more details including exam- ples. @@ -112,8 +112,8 @@ POSTQUEUE(1) POSTQUEUE(1) environment parameter. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. command_directory (see 'postconf -d' output) The location of all postfix administrative com- diff --git a/postfix/html/proxymap.8.html b/postfix/html/proxymap.8.html index 6f72fc5fe..57eca5eb4 100644 --- a/postfix/html/proxymap.8.html +++ b/postfix/html/proxymap.8.html @@ -83,7 +83,7 @@ PROXYMAP(8) PROXYMAP(8) In Postfix version 2.2 and later, the proxymap client rec- ognizes requests to access a table for security-sensitive purposes, and opens the table directly. This allows the - same main.cf setting to be used by sensitive and non-sen- + same main.cf setting to be used by sensitive and non-sen- sitive processes. DIAGNOSTICS @@ -96,15 +96,15 @@ PROXYMAP(8) PROXYMAP(8) CONFIGURATION PARAMETERS On busy mail systems a long time may pass before prox- - ymap(8) relevant changes to main.cf are picked up. Use the + ymap(8) relevant changes to main.cf are picked up. Use the command "postfix reload" to speed up a change. The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/qmqpd.8.html b/postfix/html/qmqpd.8.html index 89a21f4b7..8f244435a 100644 --- a/postfix/html/qmqpd.8.html +++ b/postfix/html/qmqpd.8.html @@ -43,7 +43,7 @@ QMQPD(8) QMQPD(8) is left up to the client to handle the situation. CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically, as + Changes to main.cf are picked up automatically, as qmqpd(8) processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. @@ -100,8 +100,8 @@ QMQPD(8) QMQPD(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/scache.8.html b/postfix/html/scache.8.html index c5f6621ef..868e14f53 100644 --- a/postfix/html/scache.8.html +++ b/postfix/html/scache.8.html @@ -86,7 +86,7 @@ SCACHE(8) SCACHE(8) without the appropriate protocol specific handshake. CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically as + Changes to main.cf are picked up automatically as scache(8) processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. @@ -106,8 +106,8 @@ SCACHE(8) SCACHE(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/sendmail.1.html b/postfix/html/sendmail.1.html index faa2317e4..c2e465ded 100644 --- a/postfix/html/sendmail.1.html +++ b/postfix/html/sendmail.1.html @@ -57,7 +57,7 @@ SENDMAIL(1) SENDMAIL(1) These and other features can be selected by specifying the appropriate combination of command-line options. Some fea- - tures are controlled by parameters in the main.cf configu- + tures are controlled by parameters in the main.cf configu- ration file. The following options are recognized: @@ -110,57 +110,58 @@ SENDMAIL(1) SENDMAIL(1) -C config_file -C config_dir - The path name of the Postfix main.cf file, or of + The path name of the Postfix main.cf file, or of its parent directory. This information is ignored with Postfix versions before 2.3. - With older Postfix versions, specify a directory - pathname with the MAIL_CONFIG environment variable - to override the location of configuration files. + With all Postfix versions, you can specify a direc- + tory pathname with the MAIL_CONFIG environment + variable to override the location of configuration + files. -F full_name - Set the sender full name. This is used only with + Set the sender full name. This is used only with messages that have no From: message header. -f sender Set the envelope sender address. This is the - address where delivery problems are sent to. With + address where delivery problems are sent to. With Postfix versions before 2.1, the Errors-To: message header overrides the error return address. - -G Gateway (relay) submission, as opposed to initial - user submission. Either do not rewrite addresses - at all, or update incomplete addresses with the + -G Gateway (relay) submission, as opposed to initial + user submission. Either do not rewrite addresses + at all, or update incomplete addresses with the domain information specified with remote_header_re- write_domain. - This option is ignored before Postfix version 2.3. + This option is ignored before Postfix version 2.3. -h hop_count (ignored) - Hop count limit. Use the hopcount_limit configura- + Hop count limit. Use the hopcount_limit configura- tion parameter instead. - -I Initialize alias database. See the newaliases com- + -I Initialize alias database. See the newaliases com- mand above. - -i When reading a message from standard input, don't - treat a line with only a . character as the end of + -i When reading a message from standard input, don't + treat a line with only a . character as the end of input. -L label (ignored) - The logging label. Use the syslog_name configura- + The logging label. Use the syslog_name configura- tion parameter instead. -m (ignored) Backwards compatibility. -N dsn (default: 'delay, failure') - Delivery status notification control. Specify - either a comma-separated list with one or more of - failure (send notification when delivery fails), + Delivery status notification control. Specify + either a comma-separated list with one or more of + failure (send notification when delivery fails), delay (send notification when delivery is delayed), - or success (send notification when the message is - delivered); or specify never (don't send any noti- + or success (send notification when the message is + delivered); or specify never (don't send any noti- fications at all). This feature is available in Postfix 2.3 and later. @@ -169,7 +170,7 @@ SENDMAIL(1) SENDMAIL(1) Backwards compatibility. -oAalias_database - Non-default alias database. Specify pathname or + Non-default alias database. Specify pathname or type:pathname. See postalias(1) for details. -O option=value (ignored) @@ -179,60 +180,60 @@ SENDMAIL(1) SENDMAIL(1) -o8 (ignored) To send 8-bit or binary content, use an appropriate - MIME encapsulation and specify the appropriate -B + MIME encapsulation and specify the appropriate -B command-line option. - -oi When reading a message from standard input, don't - treat a line with only a . character as the end of + -oi When reading a message from standard input, don't + treat a line with only a . character as the end of input. -om (ignored) - The sender is never eliminated from alias etc. + The sender is never eliminated from alias etc. expansions. -o x value (ignored) - Set option x to value. Use the equivalent configu- - ration parameter in main.cf instead. + Set option x to value. Use the equivalent configu- + ration parameter in main.cf instead. -r sender Set the envelope sender address. This is the - address where delivery problems are sent to. With + address where delivery problems are sent to. With Postfix versions before 2.1, the Errors-To: message header overrides the error return address. -R return_limit (ignored) - Limit the size of bounced mail. Use the - bounce_size_limit configuration parameter instead. + Limit the size of bounced mail. Use the + bounce_size_limit configuration parameter instead. - -q Attempt to deliver all queued mail. This is imple- + -q Attempt to deliver all queued mail. This is imple- mented by executing the postqueue(1) command. Warning: flushing undeliverable mail frequently - will result in poor delivery performance of all + will result in poor delivery performance of all other mail. -qinterval (ignored) - The interval between queue runs. Use the + The interval between queue runs. Use the queue_run_delay configuration parameter instead. -qRsite - Schedule immediate delivery of all mail that is + Schedule immediate delivery of all mail that is queued for the named site. This option accepts only - site names that are eligible for the "fast flush" - service, and is implemented by executing the + site names that are eligible for the "fast flush" + service, and is implemented by executing the postqueue(1) command. See flush(8) for more infor- mation about the "fast flush" service. -qSsite - This command is not implemented. Use the slower + This command is not implemented. Use the slower "sendmail -q" command instead. - -t Extract recipients from message headers. These are - added to any recipients specified on the command + -t Extract recipients from message headers. These are + added to any recipients specified on the command line. - With Postfix versions prior to 2.1, this option - requires that no recipient addresses are specified + With Postfix versions prior to 2.1, this option + requires that no recipient addresses are specified on the command line. -U (ignored) @@ -245,41 +246,41 @@ SENDMAIL(1) SENDMAIL(1) This feature is available in Postfix 2.3 and later. -XV (Postfix 2.2 and earlier: -V) - Variable Envelope Return Path. Given an envelope - sender address of the form owner-listname@origin, - each recipient user@domain receives mail with a + Variable Envelope Return Path. Given an envelope + sender address of the form owner-listname@origin, + each recipient user@domain receives mail with a personalized envelope sender address. - By default, the personalized envelope sender - address is owner-listname+user=domain@origin. The - default + and = characters are configurable with - the default_verp_delimiters configuration parame- + By default, the personalized envelope sender + address is owner-listname+user=domain@origin. The + default + and = characters are configurable with + the default_verp_delimiters configuration parame- ter. -XVxy (Postfix 2.2 and earlier: -Vxy) - As -XV, but uses x and y as the VERP delimiter - characters, instead of the characters specified - with the default_verp_delimiters configuration + As -XV, but uses x and y as the VERP delimiter + characters, instead of the characters specified + with the default_verp_delimiters configuration parameter. - -v Send an email report of the first delivery attempt - (Postfix versions 2.1 and later). Mail delivery - always happens in the background. When multiple -v + -v Send an email report of the first delivery attempt + (Postfix versions 2.1 and later). Mail delivery + always happens in the background. When multiple -v options are given, enable verbose logging for debugging purposes. -X log_file (ignored) - Log mailer traffic. Use the debug_peer_list and - debug_peer_level configuration parameters instead. + Log mailer traffic. Use the debug_peer_list and + debug_peer_level configuration parameters instead. SECURITY - By design, this program is not set-user (or group) id. - However, it must handle data from untrusted users or - untrusted machines. Thus, the usual precautions need to + By design, this program is not set-user (or group) id. + However, it must handle data from untrusted users or + untrusted machines. Thus, the usual precautions need to be taken against malicious inputs. DIAGNOSTICS - Problems are logged to syslogd(8) and to the standard + Problems are logged to syslogd(8) and to the standard error stream. ENVIRONMENT @@ -291,17 +292,17 @@ SENDMAIL(1) SENDMAIL(1) MAIL_DEBUG Enable debugging with an external command, as spec- - ified with the debugger_command configuration + ified with the debugger_command configuration parameter. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. The text below provides only a parameter - summary. See postconf(5) for more details including exam- + summary. See postconf(5) for more details including exam- ples. TROUBLE SHOOTING CONTROLS - The DEBUG_README file gives examples of how to trouble + The DEBUG_README file gives examples of how to trouble shoot a Postfix system. debugger_command (empty) @@ -309,29 +310,29 @@ SENDMAIL(1) SENDMAIL(1) mon program is invoked with the -D option. debug_peer_level (2) - The increment in verbose logging level when a - remote client or server matches a pattern in the + The increment in verbose logging level when a + remote client or server matches a pattern in the debug_peer_list parameter. debug_peer_list (empty) - Optional list of remote client or server hostname - or network address patterns that cause the verbose - logging level to increase by the amount specified + Optional list of remote client or server hostname + or network address patterns that cause the verbose + logging level to increase by the amount specified in $debug_peer_level. ACCESS CONTROLS Available in Postfix version 2.2 and later: authorized_flush_users (static:anyone) - List of users who are authorized to flush the + List of users who are authorized to flush the queue. authorized_mailq_users (static:anyone) List of users who are authorized to view the queue. authorized_submit_users (static:anyone) - List of users who are authorized to submit mail - with the sendmail(1) command (and with the privi- + List of users who are authorized to submit mail + with the sendmail(1) command (and with the privi- leged postdrop(1) helper command). RESOURCE AND RATE CONTROLS @@ -340,7 +341,7 @@ SENDMAIL(1) SENDMAIL(1) sent in a non-delivery notification. fork_attempts (5) - The maximal number of attempts to fork() a child + The maximal number of attempts to fork() a child process. fork_delay (1s) @@ -348,11 +349,11 @@ SENDMAIL(1) SENDMAIL(1) process. hopcount_limit (50) - The maximal number of Received: message headers + The maximal number of Received: message headers that is allowed in the primary message headers. queue_run_delay (1000s) - The time between deferred queue scans by the queue + The time between deferred queue scans by the queue manager. FAST FLUSH CONTROLS @@ -361,37 +362,37 @@ SENDMAIL(1) SENDMAIL(1) fast_flush_domains ($relay_domains) Optional list of destinations that are eligible for - per-destination logfiles with mail that is queued + per-destination logfiles with mail that is queued to those destinations. VERP CONTROLS The VERP_README file describes configuration and operation - details of Postfix support for variable envelope return + details of Postfix support for variable envelope return path addresses. default_verp_delimiters (+=) The two default VERP delimiter characters. verp_delimiter_filter (-=+) - The characters Postfix accepts as VERP delimiter - characters on the Postfix sendmail(1) command line + The characters Postfix accepts as VERP delimiter + characters on the Postfix sendmail(1) command line and in SMTP commands. MISCELLANEOUS CONTROLS alias_database (see 'postconf -d' output) - The alias databases for local(8) delivery that are + The alias databases for local(8) delivery that are updated with "newaliases" or with "sendmail -bi". command_directory (see 'postconf -d' output) - The location of all postfix administrative com- + The location of all postfix administrative com- mands. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_directory (see 'postconf -d' output) - The directory with Postfix support programs and + The directory with Postfix support programs and daemon programs. default_database_type (see 'postconf -d' output) @@ -399,16 +400,17 @@ SENDMAIL(1) SENDMAIL(1) postalias(1) and postmap(1) commands. delay_warning_time (0h) - The time after which the sender receives the mes- + The time after which the sender receives the mes- sage headers of mail that is still queued. enable_errors_to (no) - Report mail delivery errors to the address speci- - fied with the non-standard Errors-To: message - header, instead of the envelope sender address - (this feature is removed with Postfix 2.2, is - turned off by default with Postfix 2.1, and is - always turned on with older Postfix versions). + Report mail delivery errors to the address speci- + fied with the non-standard Errors-To: message + header, instead of the envelope sender address + (this feature is removed with Postfix version 2.2, + is turned off by default with Postfix version 2.1, + and is always turned on with older Postfix ver- + sions). mail_owner (postfix) The UNIX system account that owns the Postfix queue diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 371d10f56..303b46bfd 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -821,7 +821,7 @@ SMTPD(8) SMTPD(8) reject_non_fqdn_sender or reject_non_fqdn_recipient restriction. - plaintext_reject_code (450) + plaintext_reject_code (450) The numerical Postfix SMTP server response code when a request is rejected by the reject_plain- text_session restriction. diff --git a/postfix/html/tlsmgr.8.html b/postfix/html/tlsmgr.8.html index c7e007230..e2b15e73e 100644 --- a/postfix/html/tlsmgr.8.html +++ b/postfix/html/tlsmgr.8.html @@ -56,7 +56,7 @@ TLSMGR(8) TLSMGR(8) files. CONFIGURATION PARAMETERS - Changes to main.cf are not picked up automatically, + Changes to main.cf are not picked up automatically, because tlsmgr(8) is a persistent processes. Use the com- mand "postfix reload" after a configuration change. @@ -108,8 +108,8 @@ TLSMGR(8) TLSMGR(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/trivial-rewrite.8.html b/postfix/html/trivial-rewrite.8.html index 007e70dd7..2e045a1e6 100644 --- a/postfix/html/trivial-rewrite.8.html +++ b/postfix/html/trivial-rewrite.8.html @@ -43,7 +43,7 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) transport The delivery agent to use. This is the first - field of an entry in the master.cf file. + field of an entry in the master.cf file. nexthop The host to send to and optional delivery @@ -85,7 +85,7 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) Problems and transactions are logged to syslogd(8). CONFIGURATION PARAMETERS - On busy mail systems a long time may pass before a main.cf + On busy mail systems a long time may pass before a main.cf change affecting trivial-rewrite(8) is picked up. Use the command "postfix reload" to speed up a change. @@ -234,8 +234,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/html/virtual.8.html b/postfix/html/virtual.8.html index 2af3c6a2d..a78b7914c 100644 --- a/postfix/html/virtual.8.html +++ b/postfix/html/virtual.8.html @@ -152,7 +152,7 @@ VIRTUAL(8) VIRTUAL(8) maintaining three tables, use an LDAP or MYSQL database. CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically, as vir- + Changes to main.cf are picked up automatically, as vir- tual(8) processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. @@ -191,9 +191,9 @@ VIRTUAL(8) VIRTUAL(8) tual_transport mail delivery transport. virtual_transport (virtual) - The default mail delivery transport for domains - that match the $virtual_mailbox_domains parameter - value. + The default mail delivery transport and next-hop + destination for final delivery to domains listed + with $virtual_mailbox_domains. LOCKING CONTROLS virtual_mailbox_lock (see 'postconf -d' output) @@ -230,8 +230,8 @@ VIRTUAL(8) VIRTUAL(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and - master.cf configuration files. + The default location of the Postfix main.cf and + master.cf configuration files. daemon_timeout (18000s) How much time a Postfix daemon process may take to diff --git a/postfix/man/Makefile.in b/postfix/man/Makefile.in index 99c7daaf5..31e948f6f 100644 --- a/postfix/man/Makefile.in +++ b/postfix/man/Makefile.in @@ -36,7 +36,7 @@ clobber: man8/bounce.8: ../src/bounce/bounce.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/defer.8: @@ -44,37 +44,37 @@ man8/defer.8: man8/cleanup.8: ../src/cleanup/cleanup.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/anvil.8: ../src/anvil/anvil.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/scache.8: ../src/scache/scache.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/discard.8: ../src/discard/discard.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/error.8: ../src/error/error.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/flush.8: ../src/flush/flush.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/local.8: ../src/local/local.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/lmtp.8: @@ -82,12 +82,12 @@ man8/lmtp.8: man8/master.8: ../src/master/master.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/oqmgr.8: ../src/oqmgr/qmgr.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? | \ sed -e 's/qmgr[^_]/o&/' \ -e 's/qmgr$$/o&/' \ @@ -95,57 +95,57 @@ man8/oqmgr.8: ../src/oqmgr/qmgr.c man8/pickup.8: ../src/pickup/pickup.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/pipe.8: ../src/pipe/pipe.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/proxymap.8: ../src/proxymap/proxymap.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/qmgr.8: ../src/qmgr/qmgr.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/qmqpd.8: ../src/qmqpd/qmqpd.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/showq.8: ../src/showq/showq.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/spawn.8: ../src/spawn/spawn.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/smtp.8: ../src/smtp/smtp.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/smtpd.8: ../src/smtpd/smtpd.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/virtual.8: ../src/virtual/virtual.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/verify.8: ../src/verify/verify.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/trace.8: @@ -153,72 +153,72 @@ man8/trace.8: man8/tlsmgr.8: ../src/tlsmgr/tlsmgr.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man8/trivial-rewrite.8: ../src/trivial-rewrite/trivial-rewrite.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postalias.1: ../src/postalias/postalias.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postcat.1: ../src/postcat/postcat.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postconf.1: ../src/postconf/postconf.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postdrop.1: ../src/postdrop/postdrop.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postfix.1: ../src/postfix/postfix.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postkick.1: ../src/postkick/postkick.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postlock.1: ../src/postlock/postlock.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postlog.1: ../src/postlog/postlog.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postmap.1: ../src/postmap/postmap.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postqueue.1: ../src/postqueue/postqueue.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/postsuper.1: ../src/postsuper/postsuper.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/sendmail.1: ../src/sendmail/sendmail.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/mailq.1: @@ -283,12 +283,12 @@ man5/virtual.5: ../proto/virtual man1/smtp-sink.1: ../src/smtpstone/smtp-sink.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/smtp-source.1: ../src/smtpstone/smtp-source.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man5/tcp_table.5: ../proto/tcp_table @@ -296,15 +296,15 @@ man5/tcp_table.5: ../proto/tcp_table man1/qmqp-sink.1: ../src/smtpstone/qmqp-sink.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/qmqp-source.1: ../src/smtpstone/qmqp-source.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ - (cmp -s junk $? || mv junk $?) + (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ man1/qshape.1: ../auxiliary/qshape/qshape.pl #../mantools/fixman ../proto/postconf.proto $? >junk && \ - # (cmp -s junk $? || mv junk $?) + # (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman - $? >$@ diff --git a/postfix/man/man1/postalias.1 b/postfix/man/man1/postalias.1 index 1c80de7e2..c8bd57491 100644 --- a/postfix/man/man1/postalias.1 +++ b/postfix/man/man1/postalias.1 @@ -31,6 +31,15 @@ programs. The format of Postfix alias input files is described in \fBaliases\fR(5). +By default the lookup key is mapped to lowercase to make +the lookups case insensitive; as of Postfix 2.3 this case +folding happens only with tables whose lookup keys are +fixed-case strings such as btree:, dbm: or hash:. With +earlier versions, the lookup key is folded even with tables +where a lookup field can match both upper and lower case +text, such as regexp: and pcre:. This resulted in loss of +information with $\fInumber\fR substitutions. + Options: .IP "\fB-c \fIconfig_dir\fR" Read the \fBmain.cf\fR configuration file in the named directory @@ -44,7 +53,7 @@ values from the standard input stream. The exit status is zero when at least one of the requested keys was found. .IP \fB-f\fR Do not fold the lookup key to lower case while creating or querying -a map. +a table. .IP \fB-i\fR Incremental mode. Read entries from standard input and do not truncate an existing database. By default, \fBpostalias\fR(1) creates diff --git a/postfix/man/man1/postmap.1 b/postfix/man/man1/postmap.1 index 0674e23ac..dc3e9bce7 100644 --- a/postfix/man/man1/postmap.1 +++ b/postfix/man/man1/postmap.1 @@ -50,8 +50,16 @@ starts with whitespace continues a logical line. The \fIkey\fR and \fIvalue\fR are processed as is, except that surrounding white space is stripped off. Unlike with Postfix alias databases, quotes cannot be used to protect lookup keys that contain -special characters such as `#' or whitespace. The \fIkey\fR is mapped -to lowercase to make mapping lookups case insensitive. +special characters such as `#' or whitespace. + +By default the lookup key is mapped to lowercase to make +the lookups case insensitive; as of Postfix 2.3 this case +folding happens only with tables whose lookup keys are +fixed-case strings such as btree:, dbm: or hash:. With +earlier versions, the lookup key is folded even with tables +where a lookup field can match both upper and lower case +text, such as regexp: and pcre:. This resulted in loss of +information with $\fInumber\fR substitutions. .SH "COMMAND-LINE ARGUMENTS" .na .nf @@ -69,7 +77,7 @@ values from the standard input stream. The exit status is zero when at least one of the requested keys was found. .IP \fB-f\fR Do not fold the lookup key to lower case while creating or querying -a map. +a table. .IP \fB-i\fR Incremental mode. Read entries from standard input and do not truncate an existing database. By default, \fBpostmap\fR(1) creates diff --git a/postfix/man/man1/sendmail.1 b/postfix/man/man1/sendmail.1 index 92f7e3a5c..eba9b7f54 100644 --- a/postfix/man/man1/sendmail.1 +++ b/postfix/man/man1/sendmail.1 @@ -97,7 +97,7 @@ The path name of the Postfix \fBmain.cf\fR file, or of its parent directory. This information is ignored with Postfix versions before 2.3. -With older Postfix versions, specify a directory pathname +With all Postfix versions, you can specify a directory pathname with the MAIL_CONFIG environment variable to override the location of configuration files. .IP "\fB-F \fIfull_name\fR @@ -347,8 +347,8 @@ mail that is still queued. .IP "\fBenable_errors_to (no)\fR" Report mail delivery errors to the address specified with the non-standard Errors-To: message header, instead of the envelope -sender address (this feature is removed with Postfix 2.2, is -turned off by default with Postfix 2.1, and is always turned on +sender address (this feature is removed with Postfix version 2.2, is +turned off by default with Postfix version 2.1, and is always turned on with older Postfix versions). .IP "\fBmail_owner (postfix)\fR" The UNIX system account that owns the Postfix queue and most Postfix diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index ddde62dd4..509579503 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -1052,7 +1052,8 @@ client request is rejected by the "defer" restriction. .PP Do not change this unless you have a complete understanding of RFC 821. .SH defer_service_name (default: defer) -The name of the \fBdefer\fR(8) service. This service maintains a record +The name of the defer service. This service is implemented by the +\fBbounce\fR(8) daemon and maintains a record of failed delivery attempts and generates non-delivery notifications. .PP This feature is available in Postfix 2.0 and later. @@ -2841,7 +2842,7 @@ The name of the \fBpickup\fR(8) service. This service picks up local mail submissions from the Postfix maildrop queue. .PP This feature is available in Postfix 2.0 and later. -.SH plaintext_session_reject_code (default: 450) +.SH plaintext_reject_code (default: 450) The numerical Postfix SMTP server response code when a request is rejected by the \fBreject_plaintext_session\fR restriction. .PP @@ -4245,52 +4246,69 @@ postfix/smtp[pid]: Host offered STARTTLS: [name.of.host] .ft R .SH smtp_tls_per_site (default: empty) Optional lookup tables with the Postfix SMTP client TLS usage -policy by next-hop domain name and by remote SMTP server hostname. +policy by next-hop destination and by remote SMTP server hostname. +When both lookups succeed, the more specific per-site policy (NONE, +MUST, etc) overrides the less specific one (MAY), and the more +secure per-site policy (MUST, etc) overrides the less secure one +(NONE). .PP -Table format: domain names or server hostnames are specified -on the left-hand side; no wildcards are allowed. On the right hand -side specify one of the following keywords: +Specify a next-hop destination or server hostname on the left-hand +side; no wildcards are allowed. The next-hop destination is either +the recipient domain, or the destination specified with a \fBtransport\fR(5) +table, the relayhost parameter, or the relay_transport parameter. +On the right hand side specify one of the following keywords: .IP "NONE" -Don't use TLS at all. +Don't use TLS at all. This overrides a less +specific \fBMAY\fR lookup result from the alternate host or next-hop +lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, +and smtp_tls_enforce_peername settings. .IP "MAY" -Try to use STARTTLS if offered, otherwise use -the unencrypted connection. -.IP "MUST" -Require usage of STARTTLS, require that the -remote SMTP server hostname matches the information in the remote -SMTP server certificate, and require that the remote SMTP server -certificate was issued by a trusted CA. +Try to use TLS if the server announces support, +otherwise use the unencrypted connection. This has less precedence +than a more specific result (including \fBNONE\fR) from the alternate +host or next-hop lookup key, and has less precedence than the more +specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername += yes". .IP "MUST_NOPEERMATCH" -Require usage of STARTTLS, but do -not require that the remote SMTP server hostname matches the -information in the remote SMTP server certificate, or that the -server certificate was issued by a trusted CA. +Require TLS encryption, but do not +require that the remote SMTP server hostname matches the information +in the remote SMTP server certificate, or that the server certificate +was issued by a trusted CA. This overrides a less secure \fBNONE\fR +or a less specific \fBMAY\fR lookup result from the alternate host +or next-hop lookup key, and overrides the global smtp_use_tls, +smtp_enforce_tls and smtp_tls_enforce_peername settings. +.IP "MUST" +Require TLS encryption, require that the remote +SMTP server hostname matches the information in the remote SMTP +server certificate, and require that the remote SMTP server certificate +was issued by a trusted CA. This overrides a less secure \fBNONE\fR +and \fBMUST_NOPEERMATCH\fR or a less specific \fBMAY\fR lookup +result from the alternate host or next-hop lookup key, and overrides +the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername +settings. .PP -Special hints for enforcement mode: since no secure DNS lookup -mechanism is available, the recommended setup is: -.IP "Postfix 2.2.9" +As long as no secure DNS lookup mechanism is available, false +hostnames in MX or CNAME responses can change the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. Even with a perfect match between the server hostname +and the server certificate, there is no guarantee that Postfix is +connected to the right server. To avoid this loophole take the +following steps: .IP \(bu -Specify "smtp_cname_overrides_servername = no". This avoids -false hostname information in DNS CNAME records that could bypass -a hostname-based TLS usage policy. +Disallow CNAME hostname overrides. In main.cf specify +"smtp_cname_overrides_servername = no". This prevents false hostname +information in DNS CNAME records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. This feature requires Postfix 2.2.9 or later. .IP \(bu -Specify local \fBtransport\fR(5) table entries for sensitive domains -with explicit smtp:[mailhost] destinations. This avoids false -hostname information in DNS MX records that could bypass a -hostname-based TLS usage policy. +Eliminate MX lookups. Specify local \fBtransport\fR(5) table entries +for sensitive domains with explicit smtp:[mailhost] or smtp:[mailhost]:port +destinations. This prevents false hostname information in DNS MX +records from changing the server hostname that Postfix uses for TLS +policy lookup and server certificate verification. .IP \(bu -Specify MUST for these mail hosts in the smtp_tls_per_site -table. -.IP "Postfix < 2.2.9" -.IP \(bu -Specify local \fBtransport\fR(5) table entries for sensitive domains -with explicit smtp:[mailhost] destinations. This avoids false -hostname information in DNS MX records that could bypass a -hostname-based TLS usage policy, but cannot avoid false hostname -information in DNS CNAME records. -.IP \(bu -Specify MUST for these mail hosts in the smtp_tls_per_site -table. +Specify MUST for these mail hosts (including [ ] and port) in +the smtp_tls_per_site table. .PP .SH smtp_tls_scert_verifydepth (default: 5) The verification depth for remote SMTP server certificates. A @@ -4675,11 +4693,12 @@ Permit the request. This restriction is useful at the end of a restriction list, to make the default policy explicit. .IP "\fBreject_multi_recipient_bounce\fR" Reject the request when the envelope sender is the null address, -and the message has multiple envelope recipients. Although this -usage is technically allowed, it seems to have no legitimate -application. +and the message has multiple envelope recipients. This usage has +rare but legitimate applications: under certain conditions, +multi-recipient mail that was posted with the DSN option NOTIFY=NEVER +may be forwarded with the null sender address. .br -Note: this restriction can only work reliably + Note: this restriction can only work reliably when used in smtpd_data_restrictions or smtpd_end_of_data_restrictions, because the total number of recipients is not known at an earlier stage of the SMTP conversation. @@ -4693,7 +4712,7 @@ Reject the request when the connection is not encrypted. This restriction should not be used before the client has had a chance to negotiate encryption with the AUTH or STARTTLS commands. .br -The plaintext_session_reject_code parameter specifies the response +The plaintext_reject_code parameter specifies the response code for rejected requests (default: 450). This feature is available in Postfix 2.3 and later. .IP "\fBreject_unauth_pipelining\fR" @@ -5985,7 +6004,8 @@ device file. Note: on OpenBSD systems specify /dev/arandom when /dev/urandom gives timeout errors. .SH trace_service_name (default: trace) -The name of the \fBtrace\fR(8) service. This service maintains a record +The name of the trace service. This service is implemented by the +\fBbounce\fR(8) daemon and maintains a record of mail deliveries and produces a mail delivery report when verbose delivery is requested with "\fBsendmail -v\fR". .PP diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 8e2dad32a..558a6b7d5 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -90,8 +90,8 @@ Available in Postfix version 2.1 only: .IP "\fBenable_errors_to (no)\fR" Report mail delivery errors to the address specified with the non-standard Errors-To: message header, instead of the envelope -sender address (this feature is removed with Postfix 2.2, is -turned off by default with Postfix 2.1, and is always turned on +sender address (this feature is removed with Postfix version 2.2, is +turned off by default with Postfix version 2.1, and is always turned on with older Postfix versions). .SH "BUILT-IN CONTENT FILTERING CONTROLS" .na diff --git a/postfix/man/man8/virtual.8 b/postfix/man/man8/virtual.8 index ca3b76163..389e578a4 100644 --- a/postfix/man/man8/virtual.8 +++ b/postfix/man/man8/virtual.8 @@ -202,8 +202,8 @@ Available in Postfix version 2.0 and later: Postfix is final destination for the specified list of domains; mail is delivered via the $virtual_transport mail delivery transport. .IP "\fBvirtual_transport (virtual)\fR" -The default mail delivery transport for domains that match the -$virtual_mailbox_domains parameter value. +The default mail delivery transport and next-hop destination for +final delivery to domains listed with $virtual_mailbox_domains. .SH "LOCKING CONTROLS" .na .nf diff --git a/postfix/mantools/dehtml b/postfix/mantools/dehtml new file mode 100755 index 000000000..cc120de84 --- /dev/null +++ b/postfix/mantools/dehtml @@ -0,0 +1,9 @@ +#!/bin/sh + +for i +do + case $i in + /*) lynx -dump file://localhost$i;; + *) lynx -dump file://localhost`pwd`/$i;; + esac +done diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 8af68581f..1b48da42e 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -293,7 +293,7 @@ while (<>) { s;\bpar[-]*\n* *[]*ent_domain_matches_subdomains\b;$&;g; s;\bpermit_mx_backup_networks\b;$&;g; s;\bpickup_service_name\b;$&;g; - s;\bplaintext_session_reject_code\b;$&;g; + s;\bplaintext_reject_code\b;$&;g; s;\bprepend_delivered_header\b;$&;g; s;\bprocess_id\b;$&;g; s;\bprocess_id_directory\b;$&;g; diff --git a/postfix/proto/CDB_README.html b/postfix/proto/CDB_README.html index 5777e7573..fd56bdc2e 100644 --- a/postfix/proto/CDB_README.html +++ b/postfix/proto/CDB_README.html @@ -54,7 +54,7 @@ available from http://www.corpit.ru/mjt/tinycdb.html.

    Tinycdb is preferred, since it is a bit faster, has additional useful functionality and is much simpler to use.

    -

    To build Postfix after you have installed CDB, use something +

    To build Postfix after you have installed tinycdb, use something like:

    @@ -65,7 +65,11 @@ like:

    "AUXLIBS=$CDB/libcdb.a" % make
    -for tinycdb, or alternatively, for the D.J.B. version:
    +
    + +

    Alternatively, for the D.J.B. version of CDB:

    + +

     % make tidy
     % CDB=../../../cdb-0.75
    diff --git a/postfix/proto/SMTPD_POLICY_README.html b/postfix/proto/SMTPD_POLICY_README.html
    index 8e8a70836..f9c60d5a8 100644
    --- a/postfix/proto/SMTPD_POLICY_README.html
    +++ b/postfix/proto/SMTPD_POLICY_README.html
    @@ -79,6 +79,7 @@ helo_name=some.domain.tld
     queue_id=8045F2AB23
     sender=foo@bar.tld
     recipient=bar@foo.tld
    +recipient_count=0
     client_address=1.2.3.4
     client_name=another.domain.tld
     reverse_client_name=another.domain.tld
    @@ -115,8 +116,19 @@ encryption_keysize=256
         

  • When an attribute value is unavailable, the client - either does not send the attribute, or sends the attribute with - an empty value ("name=").

    + either does not send the attribute, sends the attribute with + an empty value ("name="), or sends a zero value ("name=0") in + the case of a numerical attribute.

    + +
  • The "recipient" attribute is available only in the + "RCPT TO" stage, and in the "DATA" and "END-OF-MESSAGE" stages + when Postfix accepted only one recipient for the current message. +

    + +
  • The "recipient_count" attribute (Postfix 2.3 and later) + is non-zero only in the "DATA" and "END-OF-MESSAGE" stages. It + specifies the number of recipients that Postfix accepted for + the current message.

  • The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6. diff --git a/postfix/proto/TLS_README.html b/postfix/proto/TLS_README.html index 20154a37f..3888598e4 100644 --- a/postfix/proto/TLS_README.html +++ b/postfix/proto/TLS_README.html @@ -129,6 +129,11 @@ the make(1) files with the necessary definitions. This is done by invoking the command "make makefiles" in the Postfix top-level directory and with arguments as shown next.

    +

    NOTE: Do not use Gnu TLS. It will spontaneously terminate +a process with exit status code 2, instead of properly reporting +problems to Postfix, so that it can log them to the maillog file. +

    +
  • -

    Enabling TLS in the Postfix SMTP client -

    +

    Enabling TLS in the Postfix SMTP +client

    By default, TLS is disabled in the Postfix SMTP client, so no difference to plain Postfix is visible. If you enable TLS, the Postfix SMTP client will send STARTTLS when TLS support is announced by the remote SMTP server.

    -

    WARNING: MS Exchange servers will announce STARTTLS support -even when the service is not configured, so that the TLS handshake -will fail. It may be wise to not use this option on your central -mail hub, as you don't know in advance whether you are going to -connect to such a host. Instead, use the smtp_tls_per_site -recipient/site specific options that are described below.

    - -

    When the TLS handshake fails and no other server is available, -the Postfix SMTP client defers the delivery attempt, and the mail -stays in the queue.

    +

    When the server accepts the STARTTLS command, but the subsequent +TLS handshake fails, and no other server is available, the Postfix SMTP +client defers the delivery attempt, and the mail stays in the queue. After +a handshake failure, the communications channel is in an indeterminate +state and cannot be used for non-TLS deliveries.

    Example:

    @@ -962,6 +976,9 @@ stays in the queue.

    +

    Requiring TLS encryption +

    +

    You can ENFORCE the use of TLS, so that the Postfix SMTP client will not deliver mail over unencrypted connections. In this mode, the remote SMTP server hostname must match the information in the @@ -971,14 +988,14 @@ server certificate doesn't verify or the remote SMTP server hostname doesn't match, and no other server is available, the delivery attempt is deferred and the mail stays in the queue.

    -

    The remote SMTP server hostname used in the check is beyond -question, as it must be the principal hostname (no CNAME allowed -here). Checks are performed against all names provided as dNSNames +

    The remote SMTP server hostname is verified against all names +provided as dNSNames in the SubjectAlternativeName. If no dNSNames are specified, the -CommonName is checked. The behavior may be changed with the +CommonName is checked. Verification may be turned off with the smtp_tls_enforce_peername option which is discussed below.

    -

    This option is useful only if you know that you will only +

    Enforcing the use of TLS is useful if you know that you will +only connect to servers that support RFC 2487 _and_ that present server certificates that meet the above requirements. An example would be a client only sends email to one specific mailhub that offers @@ -989,10 +1006,13 @@ the necessary STARTTLS support.

     /etc/postfix/main.cf:
    -    smtp_enforce_tls = no
    +    smtp_enforce_tls = yes
     
    +

    Disabling server certificate +verification

    +

    As of RFC 2487 the requirements for hostname checking for MTA clients are not set. When TLS is required (smtp_enforce_tls = yes), the option smtp_tls_enforce_peername can be set to "no" to disable @@ -1000,106 +1020,198 @@ strict remote SMTP server hostname checking. In this case, the mail delivery will proceed regardless of the CommonName etc. listed in the certificate.

    -

    Note: the smtp_tls_enforce_peername setting has no effect on -sessions that are controlled via the smtp_tls_per_site table.

    - -

    Disabling the remote SMTP server hostname verification can -make sense in closed environment where special CAs are created. -If not used carefully, this option opens the danger of a -"man-in-the-middle" attack (the CommonName of this possible attacker -is logged).

    +

    Despite the potential for eliminating "man-in-the-middle" and +other attacks, mandatory certificate/peername verification is not +viable as a default Internet mail delivery policy at this time. A +significant fraction of TLS enabled MTAs uses self-signed certificates, +or certificates that are signed by a private certificate authority. +On a machine that delivers mail to the Internet, if you set +smtp_enforce_tls = yes, you should probably also set +smtp_tls_enforce_peername = no. You can use the per-site TLS +policies (see below) to enable full peer verification for specific +destinations that are known to have verifiable TLS server certificates. +

    Example:

     /etc/postfix/main.cf:
    -    smtp_tls_enforce_peername = yes
    +    smtp_enforce_tls = yes
    +    smtp_tls_enforce_peername = no
     
    -

    Generally, trying TLS can be a bad idea, as some servers offer -STARTTLS but the negotiation will fail leading to unexplainable -failures. Instead, it may be a good idea to choose the TLS usage -policy based on the recipient or the mailhub to which you are -connecting.

    +

    Per-site TLS policies

    -

    Deciding the TLS usage policy per recipient may be difficult, -since a single email delivery attempt can involve several recipients. -Instead, use of TLS is controlled by the Postfix next-hop destination -domain name and by the remote SMTP server hostname. If either of these -matches an entry in the smtp_tls_per_site table, appropriate action -is taken.

    +

    A small fraction of servers offer STARTTLS but the negotiation +consistently fails, leading to mail aging out of the queue and +bouncing back to the sender. In such cases, you can use the per-site +policies to disable TLS for the problem sites. Alternatively, you +can enable TLS for just a few specific sites and not enable it for +all sites.

    -

    The remote SMTP server hostname is simply the DNS name of the -server that the Postfix SMTP client connects to. The next-hop -destination is Postfix specific. By default, this is the domain -name in the recipient address, but this information can be overruled -by the transport(5) table or by the relayhost parameter setting. -In these cases the relayhost etc. must be listed in the smtp_tls_per_site -table, instead of the recipient domain name.

    + + +

    The smtp_tls_per_site table is searched for a policy that matches +the following information:

    -
    NONE
    Don't use TLS at all.
    +
    remote SMTP server hostname
    This is simply the DNS +name of the server that the Postfix SMTP client connects to; this +name may be obtained from other DNS lookups, such as MX lookups or +CNAME lookups.
    -
    MAY
    Try to use STARTTLS if offered, otherwise use -the unencrypted connection.
    - -
    MUST
    Require usage of STARTTLS, require that the -remote SMTP server hostname matches the information in the remote -SMTP server certificate, and require that the remote SMTP server -certificate was issued by a trusted CA.
    - -
    MUST_NOPEERMATCH
    Require usage of STARTTLS, but do -not require that the remote SMTP server hostname matches the -information in the remote SMTP server certificate, or that the -server certificate was issued by a trusted CA.
    +
    next-hop destination
    This is normally the domain +portion of the recipient address, but it may be overruled by +information from the transport(5) table, from the relayhost parameter +setting, or from the relay_transport setting. When it's not the +recipient domain, the next-hop destination can have the Postfix-specific +form "[name]", [name]:port", "name" or +"name:port".
    -

    The actual TLS usage policy depends not only on whether the -next-hop destination or remote SMTP server hostname are found in -the smtp_tls_per_site table, but also on the smtp_enforce_tls -setting:

    +

    When both the hostname lookup and the next-hop lookup succeed, +the host policy does not automatically override the next-hop policy. +Instead, precedence is given to either the more specific or the +more secure per-site policy as described below.

    + +

    The smtp_tls_per_site table uses a simple "name whitespace +value" format. Specify host names or next-hop destinations on +the left-hand side; no wildcards are allowed. On the right hand +side specify one of the following keywords:

    + +
    + +
    + +
    NONE
    Don't use TLS at all. This overrides a less +specific MAY lookup result from the alternate host or next-hop +lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, +and smtp_tls_enforce_peername settings.
    + +
    MAY
    Try to use TLS if the server announces support, +otherwise use the unencrypted connection. This has less precedence +than a more specific result (including NONE) from the alternate +host or next-hop lookup key, and has less precedence than the more +specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername += yes".
    + +
    MUST_NOPEERMATCH
    Require TLS encryption, but do not +require that the remote SMTP server hostname matches the information +in the remote SMTP server certificate, or that the server certificate +was issued by a trusted CA. This overrides a less secure NONE +or a less specific MAY lookup result from the alternate host +or next-hop lookup key, and overrides the global smtp_use_tls, +smtp_enforce_tls and smtp_tls_enforce_peername settings.
    + +
    MUST
    Require TLS encryption, require that the remote +SMTP server hostname matches the information in the remote SMTP +server certificate, and require that the remote SMTP server certificate +was issued by a trusted CA. This overrides a less secure NONE +and MUST_NOPEERMATCH or a less specific MAY lookup +result from the alternate host or next-hop lookup key, and overrides +the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername +settings.
    + +
    + +
    + +

    The precedences between global (main.cf) and per-site TLS +policies can be summarized as follows:

      -
    • If no match was found, the policy is applied as specified -with smtp_enforce_tls.

      +
    • When neither the remote SMTP server hostname nor the +next-hop destination are found in the smtp_tls_per_site table, the +policy is based on smtp_use_tls, smtp_enforce_tls and +smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and +"smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes".

      -
    • If a match was found, and the smtp_enforce_tls policy is -"enforce", NONE explicitly switches it off; otherwise the "enforce" -mode is used even for entries that specify MAY.

      +
    • When both hostname and next-hop destination lookups produce +a result, the more specific per-site policy (NONE, MUST, etc) +overrides the less specific one (MAY), and the more secure per-site +policy (MUST, etc) overrides the less secure one (NONE).

      + +
    • After the per-site policy lookups are combined, the result +generally overrides the global policy. The exception is the less +specific MAY per-site policy, which is overruled by the more +specific global "smtp_enforce_tls = yes" with server certificate +verification as specified with the smtp_tls_enforce_peername +parameter.

    -

    Special hint for TLS enforcement mode: since no secure DNS -lookup mechanism is available, mail can be delivered to the wrong -remote SMTP server. This is not prevented by specifying MUST for -the next-hop domain name. The recommended setup is: specify local -transport(5) table entries for sensitive domains with explicit -smtp:[mailhost] destinations (since you can assure security of this -table unlike DNS), then specify MUST for these mail hosts in the -smtp_tls_per_site table.

    +

    Closing a DNS loophole with + per-site TLS policies

    + +

    As long as no secure DNS lookup mechanism is available, false +hostnames may appear in MX or CNAME responses. Even with a perfect +match between the server hostname and the server certificate, there +is no guarantee that Postfix is connected to the right server. To +avoid this loophole take the following steps:

    + +
      + +
    • Eliminate MX lookups. Specify local transport(5) table +entries for sensitive domains with explicit smtp:[mailhost] +or smtp:[mailhost]:port destinations (you can assure +security of this table unlike DNS); in the smtp_tls_per_site table +specify the value MUST for the key [mailhost] or +smtp:[mailhost]:port. This prevents false hostname +information in DNS MX records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification.

      + +
    • Disallow CNAME hostname overrides. In main.cf specify +"smtp_cname_overrides_servername = no". This prevents false hostname +information in DNS CNAME records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. This feature requires Postfix 2.2.9 or later.

      + +

    Example:

    - -
    -
    +
    +
     /etc/postfix/main.cf:
         smtp_tls_per_site = hash:/etc/postfix/tls_per_site
    +    relayhost = [msa.example.net]:587
    +
    +/etc/postfix/tls_per_site:
    +    # relayhost exact nexthop match
    +    [msa.example.net]:587       MUST
    +
    +    # example.org (as nexthop) has MX hosts with broken TLS.
    +    example.org                 NONE
    +
    +    # Except for (as host) mx1.example.org which works.
    +    mx1.example.org             MAY
     
    +

    Discovering servers that support +TLS

    +

    As we decide on a "per site" basis whether or not to use TLS, it would be good to have a list of sites that offered "STARTTLS". We can collect it ourselves with this option.

    @@ -1123,7 +1235,7 @@ postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
    -

    Server certificate verification

    +

    Server certificate verification depth

    When verifying a remote SMTP server certificate, a verification depth of 1 is sufficient if the certificate is directly issued by @@ -1380,7 +1492,7 @@ super-user privileges.

  • Configure Postfix, by adding the following to -/etc/postfix/main.cf.

    +/etc/postfix/main.cf .

    @@ -1447,8 +1559,22 @@ protocol in order to access the tlsmgr(8) pseudo-random number
     generation (PRNG) pool, and in order to access the TLS session
     cache databases. Such a protocol cannot be run across fifos. 

    +
  • smtp_tls_per_site: the MUST_NOPEERMATCH per-site policy +cannot override the global "smtp_tls_enforce_peername = yes" setting. +

    + +
  • smtp_tls_per_site: a combined (NONE + MAY) lookup result +for (hostname and next-hop destination) produces counter-intuitive +results for different main.cf settings. TLS is enabled with +"smtp_tls_enforce_peername = no", but it is disabled when both +"smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes". +

    + +

    The smtp_tls_per_site limitations were removed by the end of +the Postfix 2.2 support cycle.

    +

    Credits

      @@ -1459,6 +1585,10 @@ Jänicke at Cottbus Technical University.
    • Wietse Venema adopted the code, did some restructuring, and compiled this part of the documentation from Lutz's documents. +
    • Victor Duchovni was instrumental with the re-implementation +of the smtp_tls_per_site code in terms of enforcement levels, which +simplified the implementation greatly. +
    diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index e4ac74bfb..e9502a3ae 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -4688,9 +4688,11 @@ a restriction list, to make the default policy explicit.
    reject_multi_recipient_bounce
    Reject the request when the envelope sender is the null address, -and the message has multiple envelope recipients. Although this -usage is technically allowed, it seems to have no legitimate -application.
    Note: this restriction can only work reliably +and the message has multiple envelope recipients. This usage has +rare but legitimate applications: under certain conditions, +multi-recipient mail that was posted with the DSN option NOTIFY=NEVER +may be forwarded with the null sender address. +
    Note: this restriction can only work reliably when used in smtpd_data_restrictions or smtpd_end_of_data_restrictions, because the total number of recipients is not known at an earlier stage of the SMTP conversation. @@ -4706,7 +4708,7 @@ is available in Postfix 2.1 and later.
    restriction should not be used before the client has had a chance to negotiate encryption with the AUTH or STARTTLS commands.
    -The plaintext_session_reject_code parameter specifies the response +The plaintext_reject_code parameter specifies the response code for rejected requests (default: 450). This feature is available in Postfix 2.3 and later. @@ -6508,7 +6510,8 @@ This feature is available in Postfix 1.1 and later. %PARAM defer_service_name defer

    -The name of the defer(8) service. This service maintains a record +The name of the defer service. This service is implemented by the +bounce(8) daemon and maintains a record of failed delivery attempts and generates non-delivery notifications.

    @@ -7550,7 +7553,8 @@ Obsolete SUN mailtool compatibility feature. Instead, use %PARAM trace_service_name trace

    -The name of the trace(8) service. This service maintains a record +The name of the trace service. This service is implemented by the +bounce(8) daemon and maintains a record of mail deliveries and produces a mail delivery report when verbose delivery is requested with "sendmail -v".

    @@ -8512,71 +8516,77 @@ CommonName of this attacker will be logged).

    %PARAM smtp_tls_per_site

    Optional lookup tables with the Postfix SMTP client TLS usage -policy by next-hop domain name and by remote SMTP server hostname. -

    +policy by next-hop destination and by remote SMTP server hostname. +When both lookups succeed, the more specific per-site policy (NONE, +MUST, etc) overrides the less specific one (MAY), and the more +secure per-site policy (MUST, etc) overrides the less secure one +(NONE).

    -

    Table format: domain names or server hostnames are specified -on the left-hand side; no wildcards are allowed. On the right hand -side specify one of the following keywords:

    +

    Specify a next-hop destination or server hostname on the left-hand +side; no wildcards are allowed. The next-hop destination is either +the recipient domain, or the destination specified with a transport(5) +table, the relayhost parameter, or the relay_transport parameter. +On the right hand side specify one of the following keywords:

    -
    NONE
    Don't use TLS at all.
    +
    NONE
    Don't use TLS at all. This overrides a less +specific MAY lookup result from the alternate host or next-hop +lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, +and smtp_tls_enforce_peername settings.
    -
    MAY
    Try to use STARTTLS if offered, otherwise use -the unencrypted connection.
    +
    MAY
    Try to use TLS if the server announces support, +otherwise use the unencrypted connection. This has less precedence +than a more specific result (including NONE) from the alternate +host or next-hop lookup key, and has less precedence than the more +specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername += yes".
    -
    MUST
    Require usage of STARTTLS, require that the -remote SMTP server hostname matches the information in the remote -SMTP server certificate, and require that the remote SMTP server -certificate was issued by a trusted CA.
    +
    MUST_NOPEERMATCH
    Require TLS encryption, but do not +require that the remote SMTP server hostname matches the information +in the remote SMTP server certificate, or that the server certificate +was issued by a trusted CA. This overrides a less secure NONE +or a less specific MAY lookup result from the alternate host +or next-hop lookup key, and overrides the global smtp_use_tls, +smtp_enforce_tls and smtp_tls_enforce_peername settings.
    -
    MUST_NOPEERMATCH
    Require usage of STARTTLS, but do -not require that the remote SMTP server hostname matches the -information in the remote SMTP server certificate, or that the -server certificate was issued by a trusted CA.
    +
    MUST
    Require TLS encryption, require that the remote +SMTP server hostname matches the information in the remote SMTP +server certificate, and require that the remote SMTP server certificate +was issued by a trusted CA. This overrides a less secure NONE +and MUST_NOPEERMATCH or a less specific MAY lookup +result from the alternate host or next-hop lookup key, and overrides +the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername +settings.
    -

    Special hints for enforcement mode: since no secure DNS lookup -mechanism is available, the recommended setup is:

    +

    As long as no secure DNS lookup mechanism is available, false +hostnames in MX or CNAME responses can change the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. Even with a perfect match between the server hostname +and the server certificate, there is no guarantee that Postfix is +connected to the right server. To avoid this loophole take the +following steps:

    -
    +
      -
      Postfix 2.2.9
      +
    • Disallow CNAME hostname overrides. In main.cf specify +"smtp_cname_overrides_servername = no". This prevents false hostname +information in DNS CNAME records from changing the server hostname +that Postfix uses for TLS policy lookup and server certificate +verification. This feature requires Postfix 2.2.9 or later. -
        +
      • Eliminate MX lookups. Specify local transport(5) table entries +for sensitive domains with explicit smtp:[mailhost] or smtp:[mailhost]:port +destinations. This prevents false hostname information in DNS MX +records from changing the server hostname that Postfix uses for TLS +policy lookup and server certificate verification. -
      • Specify "smtp_cname_overrides_servername = no". This avoids -false hostname information in DNS CNAME records that could bypass -a hostname-based TLS usage policy. +
      • Specify MUST for these mail hosts (including [ ] and port) in +the smtp_tls_per_site table. -
      • Specify local transport(5) table entries for sensitive domains -with explicit smtp:[mailhost] destinations. This avoids false -hostname information in DNS MX records that could bypass a -hostname-based TLS usage policy. - -
      • Specify MUST for these mail hosts in the smtp_tls_per_site -table. - -
      - -
      Postfix < 2.2.9
      - -
        - -
      • Specify local transport(5) table entries for sensitive domains -with explicit smtp:[mailhost] destinations. This avoids false -hostname information in DNS MX records that could bypass a -hostname-based TLS usage policy, but cannot avoid false hostname -information in DNS CNAME records. - -
      • Specify MUST for these mail hosts in the smtp_tls_per_site -table. - -
      - -
    +

    @@ -9142,7 +9152,7 @@ configuration file or rendez-vous point.

    This feature is available in Postfix 2.3 and later.

    -%PARAM plaintext_session_reject_code 450 +%PARAM plaintext_reject_code 450

    The numerical Postfix SMTP server response code when a request diff --git a/postfix/src/anvil/anvil.c b/postfix/src/anvil/anvil.c index d9e70e59d..f03d44177 100644 --- a/postfix/src/anvil/anvil.c +++ b/postfix/src/anvil/anvil.c @@ -534,12 +534,12 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident) if ((anvil_remote = (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) { attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, 0, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, 0, - ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, 0, - ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, 0, - ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, 0, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_COUNT, 0, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, 0, + ATTR_TYPE_INT, ANVIL_ATTR_MAIL, 0, + ATTR_TYPE_INT, ANVIL_ATTR_RCPT, 0, + ATTR_TYPE_INT, ANVIL_ATTR_NTLS, 0, ATTR_TYPE_END); } else { @@ -550,12 +550,12 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident) && anvil_remote->start + var_anvil_time_unit < event_time()) ANVIL_REMOTE_RSET_RATE(anvil_remote, 0); attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate, - ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail, - ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt, - ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, anvil_remote->ntls, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_COUNT, anvil_remote->count, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->rate, + ATTR_TYPE_INT, ANVIL_ATTR_MAIL, anvil_remote->mail, + ATTR_TYPE_INT, ANVIL_ATTR_RCPT, anvil_remote->rcpt, + ATTR_TYPE_INT, ANVIL_ATTR_NTLS, anvil_remote->ntls, ATTR_TYPE_END); } } @@ -626,9 +626,9 @@ static void anvil_remote_connect(VSTREAM *client_stream, const char *ident) * Respond to the local server. */ attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_COUNT, anvil_remote->count, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->rate, ATTR_TYPE_END); /* @@ -658,8 +658,8 @@ static void anvil_remote_mail(VSTREAM *client_stream, const char *ident) */ ANVIL_REMOTE_INCR_MAIL(anvil_remote); attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->mail, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->mail, ATTR_TYPE_END); /* @@ -687,8 +687,8 @@ static void anvil_remote_rcpt(VSTREAM *client_stream, const char *ident) */ ANVIL_REMOTE_INCR_RCPT(anvil_remote); attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rcpt, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->rcpt, ATTR_TYPE_END); /* @@ -716,8 +716,8 @@ static void anvil_remote_newtls(VSTREAM *client_stream, const char *ident) */ ANVIL_REMOTE_INCR_NTLS(anvil_remote); attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->ntls, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->ntls, ATTR_TYPE_END); /* @@ -756,8 +756,8 @@ static void anvil_remote_newtls_stat(VSTREAM *client_stream, const char *ident) * Respond to local server. */ attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate, ATTR_TYPE_END); } @@ -793,7 +793,7 @@ static void anvil_remote_disconnect(VSTREAM *client_stream, const char *ident) * Respond to the local server. */ attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, ATTR_TYPE_END); } @@ -900,7 +900,7 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a if (rp->name == 0) { msg_warn("unrecognized request: \"%s\", ignored", STR(request)); attr_print_plain(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL, ATTR_TYPE_END); break; } diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index c7a824ca5..1b64722b7 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -207,7 +207,7 @@ static int bounce_append_proto(char *service_name, VSTREAM *client) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf, ATTR_TYPE_FUNC, dsb_scan, (void *) dsn_buf, @@ -278,13 +278,13 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, &dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, ATTR_TYPE_END) != 7) { msg_warn("malformed request"); return (-1); @@ -335,13 +335,13 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, &dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, ATTR_TYPE_END) != 8) { msg_warn("malformed request"); @@ -407,13 +407,13 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, &dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf, ATTR_TYPE_FUNC, dsb_scan, (void *) dsn_buf, ATTR_TYPE_END) != 9) { @@ -494,7 +494,7 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv) * request-specific protocol routines take care of the remainder. */ if (attr_scan(client, ATTR_FLAG_STRICT | ATTR_FLAG_MORE, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, &command, 0) != 1) { + ATTR_TYPE_INT, MAIL_ATTR_NREQ, &command, 0) != 1) { msg_warn("malformed request"); status = -1; } else if (command == BOUNCE_CMD_VERP) { @@ -522,7 +522,7 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv) * client. */ attr_print(client, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); vstream_fflush(client); diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 5fbb28dbf..bc3ea6d77 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -74,8 +74,8 @@ /* .IP "\fBenable_errors_to (no)\fR" /* Report mail delivery errors to the address specified with the /* non-standard Errors-To: message header, instead of the envelope -/* sender address (this feature is removed with Postfix 2.2, is -/* turned off by default with Postfix 2.1, and is always turned on +/* sender address (this feature is removed with Postfix version 2.2, is +/* turned off by default with Postfix version 2.1, and is always turned on /* with older Postfix versions). /* BUILT-IN CONTENT FILTERING CONTROLS /* .ad @@ -373,7 +373,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv) ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->queue_id, ATTR_TYPE_END); if (attr_scan(src, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_END) != 1) { state->errs |= CLEANUP_STAT_BAD; flags = 0; @@ -419,7 +419,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv) */ status = cleanup_flush(state); /* in case state is modified */ attr_print(src, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_STR, MAIL_ATTR_WHY, state->reason ? state->reason : "", ATTR_TYPE_END); diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index 22f6e5094..797609778 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -289,19 +289,21 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv) if (*var_canonical_maps) cleanup_comm_canon_maps = - maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, DICT_FLAG_LOCK); + maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); if (*var_send_canon_maps) cleanup_send_canon_maps = maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); if (*var_rcpt_canon_maps) cleanup_rcpt_canon_maps = maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); if (*var_virt_alias_maps) cleanup_virt_alias_maps = maps_create(VAR_VIRT_ALIAS_MAPS, var_virt_alias_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); if (*var_canon_classes) cleanup_comm_canon_flags = name_mask(VAR_CANON_CLASSES, canon_class_table, @@ -337,11 +339,11 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv) if (*var_send_bcc_maps) cleanup_send_bcc_maps = maps_create(VAR_SEND_BCC_MAPS, var_send_bcc_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); if (*var_rcpt_bcc_maps) cleanup_rcpt_bcc_maps = maps_create(VAR_RCPT_BCC_MAPS, var_rcpt_bcc_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); flush_init(); } diff --git a/postfix/src/flush/flush.c b/postfix/src/flush/flush.c index ffdf81a41..ce98ec8b4 100644 --- a/postfix/src/flush/flush.c +++ b/postfix/src/flush/flush.c @@ -631,7 +631,7 @@ static void flush_service(VSTREAM *client_stream, char *unused_service, && mail_queue_id_ok(STR(queue_id))) status = flush_add_service(lowercase(STR(site)), STR(queue_id)); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); } else if (STREQ(STR(request), FLUSH_REQ_SEND)) { site = vstring_alloc(10); @@ -641,25 +641,25 @@ static void flush_service(VSTREAM *client_stream, char *unused_service, status = flush_send_service(lowercase(STR(site)), REFRESH_AND_DELIVER); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); } else if (STREQ(STR(request), FLUSH_REQ_REFRESH) || STREQ(STR(request), wakeup)) { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, FLUSH_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, FLUSH_STAT_OK, ATTR_TYPE_END); vstream_fflush(client_stream); (void) flush_refresh_service(var_fflush_refresh); } else if (STREQ(STR(request), FLUSH_REQ_PURGE)) { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, FLUSH_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, FLUSH_STAT_OK, ATTR_TYPE_END); vstream_fflush(client_stream); (void) flush_refresh_service(0); } } else attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); vstring_free(request); if (site) diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 1a6faf282..cb9441562 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -22,7 +22,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ sent.c smtp_stream.c split_addr.c string_list.c strip_addr.c \ sys_exits.c timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \ tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c verify.c \ - verify_clnt.c verp_sender.c virtual8_maps.c xtext.c scache_single.c \ + verify_clnt.c verp_sender.c xtext.c scache_single.c \ scache_clnt.c scache_multi.c user_acl.c mkmap_cdb.c mkmap_sdbm.c \ ehlo_mask.c \ wildcard_inet_addr.c valid_mailhost_addr.c dsn_util.c dsn_mask.c \ @@ -52,7 +52,7 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ sent.o smtp_stream.o split_addr.o string_list.o strip_addr.o \ sys_exits.o timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \ tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o verify.o \ - verify_clnt.o verp_sender.o virtual8_maps.o xtext.o scache_single.o \ + verify_clnt.o verp_sender.o xtext.o scache_single.o \ scache_clnt.o scache_multi.o user_acl.o mkmap_cdb.o mkmap_sdbm.o \ ehlo_mask.o \ wildcard_inet_addr.o valid_mailhost_addr.o dsn_util.o dsn_mask.o \ @@ -78,7 +78,7 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ rec_streamlf.h rec_type.h recipient_list.h record.h resolve_clnt.h \ resolve_local.h rewrite_clnt.h sent.h smtp_stream.h split_addr.h \ string_list.h strip_addr.h sys_exits.h timed_ipc.h tok822.h \ - trace.h verify.h verify_clnt.h verp_sender.h virtual8_maps.h \ + trace.h verify.h verify_clnt.h verp_sender.h \ xtext.h scache.h user_acl.h ehlo_mask.h db_common.h \ wildcard_inet_addr.h valid_mailhost_addr.h dsn_util.h dsn_mask.h \ dsn_attr_map.h dsn.h dsn_buf.h rcpt_buf.h rcpt_print.h dsn_print.h \ @@ -93,7 +93,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \ off_cvt quote_822_local rec2stream recdump resolve_clnt \ resolve_local rewrite_clnt stream2rec string_list tok822_parse \ quote_821_local mail_conf_time mime_state strip_addr \ - virtual8_maps verify_clnt xtext anvil_clnt scache ehlo_mask \ + verify_clnt xtext anvil_clnt scache ehlo_mask \ valid_mailhost_addr own_inet_addr LIBS = ../../lib/libutil.a @@ -244,11 +244,6 @@ strip_addr: $(LIB) $(LIBS) $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) mv junk $@.o -virtual8_maps: $(LIB) $(LIBS) - mv $@.o junk - $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) - mv junk $@.o - verify_clnt: $(LIB) $(LIBS) mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) @@ -278,7 +273,7 @@ own_inet_addr: own_inet_addr.c $(LIB) $(LIBS) tests: tok822_test mime_test mime_nest mime_8bit mime_dom mime_trunc \ mime_cvt mime_cvt2 mime_cvt3 strip_addr_test tok822_limit_test \ - virtual8_test xtext_test scache_multi_test ehlo_mask_test \ + xtext_test scache_multi_test ehlo_mask_test \ namadr_list_test tok822_test: tok822_parse tok822_parse.in tok822_parse.ref @@ -336,13 +331,6 @@ strip_addr_test: strip_addr strip_addr.ref diff strip_addr.ref strip_addr.tmp rm -f strip_addr.tmp -virtual8_test: virtual8_maps virtual8_map virtual8.in virtual8.ref \ - ../postmap/postmap - ../postmap/postmap hash:virtual8_map - ./virtual8_maps virtual8.tmp - diff virtual8.ref virtual8.tmp - rm -f virtual8.tmp virtual8_map.db - xtext_test: xtext ./xtext xtext.tmp od -cb xtext.ref @@ -690,6 +678,7 @@ dict_mysql.o: ../../include/msg.h dict_mysql.o: ../../include/mymalloc.h dict_mysql.o: ../../include/myrand.h dict_mysql.o: ../../include/split_at.h +dict_mysql.o: ../../include/stringops.h dict_mysql.o: ../../include/sys_defs.h dict_mysql.o: ../../include/vbuf.h dict_mysql.o: ../../include/vstream.h @@ -709,6 +698,7 @@ dict_pgsql.o: ../../include/msg.h dict_pgsql.o: ../../include/mymalloc.h dict_pgsql.o: ../../include/myrand.h dict_pgsql.o: ../../include/split_at.h +dict_pgsql.o: ../../include/stringops.h dict_pgsql.o: ../../include/sys_defs.h dict_pgsql.o: ../../include/vbuf.h dict_pgsql.o: ../../include/vstream.h @@ -793,6 +783,8 @@ dsn_mask.o: ../../include/msg.h dsn_mask.o: ../../include/name_code.h dsn_mask.o: ../../include/name_mask.h dsn_mask.o: ../../include/sys_defs.h +dsn_mask.o: ../../include/vbuf.h +dsn_mask.o: ../../include/vstring.h dsn_mask.o: dsn_mask.c dsn_mask.o: dsn_mask.h dsn_print.o: ../../include/attr.h @@ -814,10 +806,14 @@ dsn_util.o: dsn_util.c dsn_util.o: dsn_util.h ehlo_mask.o: ../../include/name_mask.h ehlo_mask.o: ../../include/sys_defs.h +ehlo_mask.o: ../../include/vbuf.h +ehlo_mask.o: ../../include/vstring.h ehlo_mask.o: ehlo_mask.c ehlo_mask.o: ehlo_mask.h ext_prop.o: ../../include/name_mask.h ext_prop.o: ../../include/sys_defs.h +ext_prop.o: ../../include/vbuf.h +ext_prop.o: ../../include/vstring.h ext_prop.o: ext_prop.c ext_prop.o: ext_prop.h ext_prop.o: mail_params.h @@ -871,6 +867,8 @@ hold_message.o: mail_queue.h input_transp.o: ../../include/msg.h input_transp.o: ../../include/name_mask.h input_transp.o: ../../include/sys_defs.h +input_transp.o: ../../include/vbuf.h +input_transp.o: ../../include/vstring.h input_transp.o: cleanup_user.h input_transp.o: input_transp.c input_transp.o: input_transp.h @@ -970,6 +968,7 @@ mail_conf_bool.o: ../../include/msg.h mail_conf_bool.o: ../../include/sys_defs.h mail_conf_bool.o: ../../include/vbuf.h mail_conf_bool.o: ../../include/vstream.h +mail_conf_bool.o: ../../include/vstring.h mail_conf_bool.o: mail_conf.h mail_conf_bool.o: mail_conf_bool.c mail_conf_int.o: ../../include/argv.h @@ -1064,6 +1063,7 @@ mail_dict.o: ../../include/msg.h mail_dict.o: ../../include/sys_defs.h mail_dict.o: ../../include/vbuf.h mail_dict.o: ../../include/vstream.h +mail_dict.o: ../../include/vstring.h mail_dict.o: dict_ldap.h mail_dict.o: dict_mysql.h mail_dict.o: dict_pgsql.h @@ -1072,6 +1072,8 @@ mail_dict.o: mail_dict.c mail_dict.o: mail_dict.h mail_error.o: ../../include/name_mask.h mail_error.o: ../../include/sys_defs.h +mail_error.o: ../../include/vbuf.h +mail_error.o: ../../include/vstring.h mail_error.o: mail_error.c mail_error.o: mail_error.h mail_flush.o: ../../include/attr.h @@ -1231,6 +1233,8 @@ match_parent_style.o: string_list.h mbox_conf.o: ../../include/argv.h mbox_conf.o: ../../include/name_mask.h mbox_conf.o: ../../include/sys_defs.h +mbox_conf.o: ../../include/vbuf.h +mbox_conf.o: ../../include/vstring.h mbox_conf.o: mail_params.h mbox_conf.o: mbox_conf.c mbox_conf.o: mbox_conf.h @@ -1271,6 +1275,7 @@ mkmap_cdb.o: ../../include/mymalloc.h mkmap_cdb.o: ../../include/sys_defs.h mkmap_cdb.o: ../../include/vbuf.h mkmap_cdb.o: ../../include/vstream.h +mkmap_cdb.o: ../../include/vstring.h mkmap_cdb.o: mkmap.h mkmap_cdb.o: mkmap_cdb.c mkmap_db.o: ../../include/argv.h @@ -1312,6 +1317,7 @@ mkmap_open.o: ../../include/sigdelay.h mkmap_open.o: ../../include/sys_defs.h mkmap_open.o: ../../include/vbuf.h mkmap_open.o: ../../include/vstream.h +mkmap_open.o: ../../include/vstring.h mkmap_open.o: mkmap.h mkmap_open.o: mkmap_open.c mkmap_sdbm.o: ../../include/argv.h @@ -1791,18 +1797,6 @@ verp_sender.o: ../../include/vstring.h verp_sender.o: mail_params.h verp_sender.o: verp_sender.c verp_sender.o: verp_sender.h -virtual8_maps.o: ../../include/argv.h -virtual8_maps.o: ../../include/dict.h -virtual8_maps.o: ../../include/msg.h -virtual8_maps.o: ../../include/mymalloc.h -virtual8_maps.o: ../../include/sys_defs.h -virtual8_maps.o: ../../include/vbuf.h -virtual8_maps.o: ../../include/vstream.h -virtual8_maps.o: mail_params.h -virtual8_maps.o: maps.h -virtual8_maps.o: strip_addr.h -virtual8_maps.o: virtual8_maps.c -virtual8_maps.o: virtual8_maps.h wildcard_inet_addr.o: ../../include/inet_addr_host.h wildcard_inet_addr.o: ../../include/inet_addr_list.h wildcard_inet_addr.o: ../../include/msg.h diff --git a/postfix/src/global/abounce.c b/postfix/src/global/abounce.c index 3b95f9768..f7d2dcad3 100644 --- a/postfix/src/global/abounce.c +++ b/postfix/src/global/abounce.c @@ -201,7 +201,7 @@ static void abounce_event(int unused_event, char *context) event_disable_readwrite(vstream_fileno(ap->fp)); abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) == 1 ? status : -1); } @@ -233,14 +233,14 @@ static void abounce_request_verp(const char *class, const char *service, ap->fp = mail_connect_wait(class, service); if (attr_print(ap->fp, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, command, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp, ATTR_TYPE_END) == 0 && vstream_fflush(ap->fp) == 0) { @@ -301,14 +301,14 @@ static void abounce_request(const char *class, const char *service, ap->fp = mail_connect_wait(class, service); if (attr_print(ap->fp, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, command, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0 && vstream_fflush(ap->fp) == 0) { event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap); diff --git a/postfix/src/global/anvil_clnt.c b/postfix/src/global/anvil_clnt.c index a0117cdc7..02ecac2f9 100644 --- a/postfix/src/global/anvil_clnt.c +++ b/postfix/src/global/anvil_clnt.c @@ -192,12 +192,12 @@ int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, count, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate, - ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, msgs, - ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, rcpts, - ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, newtls, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_COUNT, count, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate, + ATTR_TYPE_INT, ANVIL_ATTR_MAIL, msgs, + ATTR_TYPE_INT, ANVIL_ATTR_RCPT, rcpts, + ATTR_TYPE_INT, ANVIL_ATTR_NTLS, newtls, ATTR_TYPE_END) != 6) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) @@ -220,9 +220,9 @@ int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, count, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_COUNT, count, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate, ATTR_TYPE_END) != 3) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) @@ -245,8 +245,8 @@ int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, msgs, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, msgs, ATTR_TYPE_END) != 2) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) @@ -269,8 +269,8 @@ int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rcpts, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, rcpts, ATTR_TYPE_END) != 2) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) @@ -293,8 +293,8 @@ int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, newtls, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, newtls, ATTR_TYPE_END) != 2) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) @@ -317,8 +317,8 @@ int anvil_clnt_newtls_stat(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, ANVIL_ATTR_RATE, newtls, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_RATE, newtls, ATTR_TYPE_END) != 2) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) @@ -341,7 +341,7 @@ int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service, ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ - ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) status = ANVIL_STAT_FAIL; else if (status != ANVIL_STAT_OK) diff --git a/postfix/src/global/bounce.c b/postfix/src/global/bounce.c index 440e4ebcf..54a3059cf 100644 --- a/postfix/src/global/bounce.c +++ b/postfix/src/global/bounce.c @@ -235,8 +235,8 @@ int bounce_append(int flags, const char *id, MSG_STATS *stats, if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ? var_defer_service : var_bounce_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, @@ -277,14 +277,14 @@ int bounce_flush(int flags, const char *queue, const char *id, if (var_soft_bounce) return (-1); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0) { return (0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { @@ -310,14 +310,14 @@ int bounce_flush_verp(int flags, const char *queue, const char *id, if (var_soft_bounce) return (-1); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_VERP, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_VERP, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, ATTR_TYPE_END) == 0) { return (0); @@ -391,14 +391,14 @@ int bounce_one(int flags, const char *queue, const char *id, my_dsn.action = "failed"; if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_ONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_ONE, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, ATTR_TYPE_END) == 0 diff --git a/postfix/src/global/defer.c b/postfix/src/global/defer.c index 0f0a57b98..d98bf6f33 100644 --- a/postfix/src/global/defer.c +++ b/postfix/src/global/defer.c @@ -196,8 +196,8 @@ int defer_append(int flags, const char *id, MSG_STATS *stats, my_dsn.action = "delayed"; if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, @@ -239,14 +239,14 @@ int defer_flush(int flags, const char *queue, const char *id, flags |= BOUNCE_FLAG_DELRCPT; if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0) { return (0); } else { @@ -261,13 +261,13 @@ int defer_warn(int flags, const char *queue, const char *id, const char *sender, const char *envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0) { return (0); } else { diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index 8938e6a88..23abc30d3 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -81,7 +81,7 @@ static int deliver_pass_initial_reply(VSTREAM *stream) int stat; if (attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 1) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); stat = -1; @@ -98,7 +98,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, int stat; attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, request->flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, request->flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, request->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, request->queue_id, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, request->data_offset, @@ -107,7 +107,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, request->encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, request->sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, request->dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, request->dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, request->dsn_ret, ATTR_TYPE_FUNC, msg_stats_print, (void *) &request->msg_stats, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, request->client_name, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, request->client_addr, @@ -117,7 +117,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, request->sasl_username, ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, request->sasl_sender, ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context, - ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, 1, + ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, 1, ATTR_TYPE_END); attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, @@ -140,7 +140,7 @@ static int deliver_pass_final_reply(VSTREAM *stream, DSN_BUF *dsb) if (attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_FUNC, dsb_scan, (void *) dsb, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 2) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); return (DELIVER_PASS_UNKNOWN); diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index 029d2fdef..5c6e546dd 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -129,7 +129,7 @@ static int deliver_request_initial(VSTREAM *stream) if (msg_verbose) msg_info("deliver_request_initial: send initial status"); attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, 0, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, 0, ATTR_TYPE_END); if ((err = vstream_fflush(stream)) != 0) if (msg_verbose) @@ -157,7 +157,7 @@ static int deliver_request_final(VSTREAM *stream, DELIVER_REQUEST *request, hop_status->reason, status); attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_FUNC, dsn_print, (void *) hop_status, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); if ((err = vstream_fflush(stream)) != 0) if (msg_verbose) @@ -227,7 +227,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) * the conversation when they send bad information. */ if (attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &request->flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &request->data_offset, @@ -236,7 +236,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, address, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, &dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, ATTR_TYPE_FUNC, msg_stats_scan, (void *) &request->msg_stats, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, client_name, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, client_addr, @@ -246,7 +246,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username, ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender, ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context, - ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, &rcpt_count, + ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, &rcpt_count, ATTR_TYPE_END) != 20) { msg_warn("%s: error receiving common attributes", myname); return (-1); diff --git a/postfix/src/global/dict_ldap.c b/postfix/src/global/dict_ldap.c index eaaad4908..27f9bd603 100644 --- a/postfix/src/global/dict_ldap.c +++ b/postfix/src/global/dict_ldap.c @@ -906,6 +906,14 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) if (msg_verbose) msg_info("%s: In dict_ldap_lookup", myname); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * If they specified a domain list for this map, then only search for * addresses in domains on the list. This can significantly reduce the @@ -1145,6 +1153,8 @@ static void dict_ldap_close(DICT *dict) myfree(dict_ldap->tls_random_file); myfree(dict_ldap->tls_cipher_suite); #endif + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -1331,6 +1341,8 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) dict_ldap->dict.flags |= DICT_FLAG_PATTERN; else dict_ldap->dict.flags |= DICT_FLAG_FIXED; + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_ldap->dict.fold_buf = vstring_alloc(10); attr = cfg_get_str(dict_ldap->parser, "result_attribute", "maildrop", 0, 0); diff --git a/postfix/src/global/dict_mysql.c b/postfix/src/global/dict_mysql.c index 282366c6c..0e82eaa0f 100644 --- a/postfix/src/global/dict_mysql.c +++ b/postfix/src/global/dict_mysql.c @@ -187,6 +187,7 @@ #include "find_inet.h" #include "myrand.h" #include "events.h" +#include "stringops.h" /* Global library. */ @@ -303,7 +304,15 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name) db_quote_callback_t quote_func = dict_mysql_quote; dict_errno = 0; - + + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * If there is a domain list for this map, then only search for * addresses in domains on the list. This can significantly reduce @@ -619,6 +628,8 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf) dict_mysql->dict.flags |= DICT_FLAG_PATTERN; else dict_mysql->dict.flags |= DICT_FLAG_FIXED; + if (dict_mysql->dict.flags & DICT_FLAG_FOLD_FIX) + dict_mysql->dict.fold_buf = vstring_alloc(10); hosts = cfg_get_str(p, "hosts", "", 0, 0); @@ -744,6 +755,8 @@ static void dict_mysql_close(DICT *dict) argv_free(dict_mysql->hosts); if (dict_mysql->ctx) db_common_free_ctx(dict_mysql->ctx); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } diff --git a/postfix/src/global/dict_pgsql.c b/postfix/src/global/dict_pgsql.c index 976168eba..acaf6e786 100644 --- a/postfix/src/global/dict_pgsql.c +++ b/postfix/src/global/dict_pgsql.c @@ -167,6 +167,7 @@ #include "find_inet.h" #include "myrand.h" #include "events.h" +#include "stringops.h" /* Global library. */ @@ -302,6 +303,15 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) INIT_VSTR(result, 10); dict_errno = 0; + + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * If there is a domain list for this map, then only search for * addresses in domains on the list. This can significantly reduce @@ -585,6 +595,8 @@ static void pgsql_parse_config(DICT_PGSQL *dict_pgsql, const char *pgsqlcf) dict_pgsql->dict.flags |= DICT_FLAG_PATTERN; else dict_pgsql->dict.flags |= DICT_FLAG_FIXED; + if (dict_pgsql->dict.flags & DICT_FLAG_FOLD_FIX) + dict_pgsql->dict.fold_buf = vstring_alloc(10); hosts = cfg_get_str(p, "hosts", "", 0, 0); @@ -691,6 +703,8 @@ static void dict_pgsql_close(DICT *dict) argv_free(dict_pgsql->hosts); if (dict_pgsql->ctx) db_common_free_ctx(dict_pgsql->ctx); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c index f4eea08bd..5ce496af7 100644 --- a/postfix/src/global/dict_proxy.c +++ b/postfix/src/global/dict_proxy.c @@ -106,20 +106,21 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_LOOKUP, ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict->name, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, dict_proxy->in_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, dict_proxy->in_flags, ATTR_TYPE_STR, MAIL_ATTR_KEY, key, ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_VALUE, dict_proxy->result, ATTR_TYPE_END) != 2) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream)); } else { if (msg_verbose) - msg_info("%s: table=%s flags=0%o key=%s -> status=%d result=%s", - myname, dict->name, dict_proxy->in_flags, key, + msg_info("%s: table=%s flags=%s key=%s -> status=%d result=%s", + myname, dict->name, + dict_flags_str(dict_proxy->in_flags), key, status, STR(dict_proxy->result)); switch (status) { case PROXY_STAT_BAD: @@ -225,19 +226,20 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_OPEN, ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict_proxy->dict.name, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, dict_proxy->in_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, dict_proxy->in_flags, ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &server_flags, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &server_flags, ATTR_TYPE_END) != 2) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname); } else { if (msg_verbose) - msg_info("%s: connect to map=%s status=%d server_flags=0%o", - myname, dict_proxy->dict.name, status, server_flags); + msg_info("%s: connect to map=%s status=%d server_flags=%s", + myname, dict_proxy->dict.name, status, + dict_flags_str(server_flags)); switch (status) { case PROXY_STAT_BAD: msg_fatal("%s open failed for table \"%s\": invalid request", diff --git a/postfix/src/global/dsn_mask.c b/postfix/src/global/dsn_mask.c index 83d36a87c..251f6f6ac 100644 --- a/postfix/src/global/dsn_mask.c +++ b/postfix/src/global/dsn_mask.c @@ -117,6 +117,7 @@ int dsn_notify_mask(const char *str) const char *dsn_notify_str(int mask) { - return (str_name_mask_opt("DSN NOTIFY command", dsn_notify_table, - mask, NAME_MASK_FATAL | NAME_MASK_COMMA)); + return (str_name_mask_opt((VSTRING *) 0, "DSN NOTIFY command", + dsn_notify_table, mask, + NAME_MASK_FATAL | NAME_MASK_COMMA)); } diff --git a/postfix/src/global/ehlo_mask.ref b/postfix/src/global/ehlo_mask.ref index 4c6dab355..e865ab65c 100644 --- a/postfix/src/global/ehlo_mask.ref +++ b/postfix/src/global/ehlo_mask.ref @@ -1,3 +1,3 @@ -starttls, 8bitmime, verp, etrn, etrn -> 0x51 -> 8BITMIME ETRN VERP -foobar, auth, pipelining, size, vrfy -> 0x2e -> AUTH PIPELINING SIZE VRFY -xclient, xforward -> 0x180 -> XCLIENT XFORWARD +starttls, 8bitmime, verp, etrn, etrn -> 0xd1 -> 8BITMIME ETRN VERP STARTTLS +foobar, auth, pipelining, size, vrfy -> 0x2e -> AUTH PIPELINING SIZE VRFY +xclient, xforward -> 0x300 -> XCLIENT XFORWARD diff --git a/postfix/src/global/mail_addr_find.c b/postfix/src/global/mail_addr_find.c index cda022b04..1ebbbc20b 100644 --- a/postfix/src/global/mail_addr_find.c +++ b/postfix/src/global/mail_addr_find.c @@ -13,7 +13,8 @@ /* DESCRIPTION /* mail_addr_find() searches the specified maps for an entry with as /* key the specified address, and derivations from that address. -/* The search is case insensitive. +/* It is up to the caller to specify its case sensitivity +/* preferences when it opens the maps. /* The result is overwritten upon each call. /* /* An address that is in the form \fIuser\fR matches itself. @@ -103,7 +104,7 @@ const char *mail_addr_find(MAPS *path, const char *address, char **extp) /* * Initialize. */ - full_key = lowercase(mystrdup(address)); + full_key = mystrdup(address); if (*var_rcpt_delim == 0) { bare_key = saved_ext = 0; } else { @@ -199,7 +200,7 @@ int main(int argc, char **argv) * Initialize. */ mail_conf_read(); - path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK); + path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { extent = 0; result = mail_addr_find(path, STR(buffer), &extent); diff --git a/postfix/src/global/mail_addr_map.c b/postfix/src/global/mail_addr_map.c index ad0c6c394..c8a6e2c9f 100644 --- a/postfix/src/global/mail_addr_map.c +++ b/postfix/src/global/mail_addr_map.c @@ -175,7 +175,7 @@ int main(int argc, char **argv) msg_verbose = 1; if (chdir(var_queue_dir) < 0) msg_fatal("chdir %s: %m", var_queue_dir); - path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK); + path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { msg_info("=== Address extension on, extension propagation on ==="); UPDATE(var_rcpt_delim, "+"); diff --git a/postfix/src/global/mail_command_client.c b/postfix/src/global/mail_command_client.c index fc1c56c9e..db4360972 100644 --- a/postfix/src/global/mail_command_client.c +++ b/postfix/src/global/mail_command_client.c @@ -75,7 +75,7 @@ int mail_command_client(const char *class, const char *name,...) va_end(ap); if (status != 0 || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, 0) != 1) + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, 0) != 1) status = -1; (void) vstream_fclose(stream); return (status); diff --git a/postfix/src/global/mail_stream.c b/postfix/src/global/mail_stream.c index e7e43e1ff..ce4ad033f 100644 --- a/postfix/src/global/mail_stream.c +++ b/postfix/src/global/mail_stream.c @@ -298,11 +298,11 @@ static int mail_stream_finish_ipc(MAIL_STREAM *info, VSTRING *why) * Receive the peer's completion status. */ if ((why && attr_scan(info->stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, ATTR_TYPE_END) != 2) || (!why && attr_scan(info->stream, ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1)) status = CLEANUP_STAT_WRITE; diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f77b11e48..eb592a07d 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20060112" +#define MAIL_RELEASE_DATE "20060123" #define MAIL_VERSION_NUMBER "2.3" #ifdef SNAPSHOT diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c index ad97ee6d6..d1c705b91 100644 --- a/postfix/src/global/maps.c +++ b/postfix/src/global/maps.c @@ -24,13 +24,13 @@ /* locking. Dictionaries are opened read-only, and in-memory /* dictionary instances are shared. /* -/* Lookups are case sensitive. -/* /* maps_create() takes list of type:name pairs and opens the /* named dictionaries. /* The result is a handle that must be specified along with all /* other maps_xxx() operations. /* See dict_open(3) for a description of flags. +/* This includes the flags that specify preferences for search +/* string case folding. /* /* maps_find() searches the specified list of dictionaries /* in the specified order for the named key. The result is in @@ -49,6 +49,10 @@ /* .IP map_names /* Null-terminated string with type:name dictionary specifications, /* separated by whitespace or commas. +/* .IP flags +/* With maps_create(), flags that are passed to dict_open(). +/* With maps_find(), flags that control searching behavior +/* as documented above. /* .IP maps /* A result from maps_create(). /* .IP key @@ -133,8 +137,9 @@ MAPS *maps_create(const char *title, const char *map_names, int dict_flags) #define OPEN_FLAGS O_RDONLY while ((map_type_name = mystrtok(&bufp, sep)) != 0) { - vstring_sprintf(map_type_name_flags, "%s(%o,%o)", - map_type_name, OPEN_FLAGS, dict_flags); + vstring_sprintf(map_type_name_flags, "%s(%o,%s)", + map_type_name, OPEN_FLAGS, + dict_flags_str(dict_flags)); if ((dict = dict_handle(vstring_str(map_type_name_flags))) == 0) dict = dict_open(map_type_name, OPEN_FLAGS, dict_flags); if ((dict->flags & dict_flags) != dict_flags) diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c index e1c46796d..ec53be5ef 100644 --- a/postfix/src/global/post_mail.c +++ b/postfix/src/global/post_mail.c @@ -198,7 +198,7 @@ static void post_mail_init(VSTREAM *stream, const char *sender, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_END) != 1 || attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) msg_fatal("unable to contact the %s service", var_cleanup_service); @@ -423,7 +423,7 @@ int post_mail_fclose(VSTREAM *cleanup) rec_fputs(cleanup, REC_TYPE_END, ""); if (vstream_fflush(cleanup) || attr_scan(cleanup, ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) status = CLEANUP_STAT_WRITE; } diff --git a/postfix/src/global/rcpt_buf.c b/postfix/src/global/rcpt_buf.c index cfb1b4178..3c8edddad 100644 --- a/postfix/src/global/rcpt_buf.c +++ b/postfix/src/global/rcpt_buf.c @@ -130,7 +130,7 @@ int rcpb_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &rcpt->offset, ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, &rcpt->dsn_notify, + ATTR_TYPE_INT, MAIL_ATTR_DSN_NOTIFY, &rcpt->dsn_notify, ATTR_TYPE_END); return (ret == 5 ? 1 : -1); } diff --git a/postfix/src/global/rcpt_print.c b/postfix/src/global/rcpt_print.c index 1c3b723f8..985f42c32 100644 --- a/postfix/src/global/rcpt_print.c +++ b/postfix/src/global/rcpt_print.c @@ -63,7 +63,7 @@ int rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset, ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify, + ATTR_TYPE_INT, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify, ATTR_TYPE_END); return (ret); } diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index fcaf2c624..50c95a783 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -233,11 +233,11 @@ void resolve_clnt(const char *class, const char *sender, ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &server_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &server_flags, ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, reply->transport, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop, ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &reply->flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &reply->flags, ATTR_TYPE_END) != 5) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c index 7aaa75688..601f7ca00 100644 --- a/postfix/src/global/rewrite_clnt.c +++ b/postfix/src/global/rewrite_clnt.c @@ -136,7 +136,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &server_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &server_flags, ATTR_TYPE_STR, MAIL_ATTR_ADDR, result, ATTR_TYPE_END) != 2) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) diff --git a/postfix/src/global/scache_clnt.c b/postfix/src/global/scache_clnt.c index c1d3a058b..10573e7df 100644 --- a/postfix/src/global/scache_clnt.c +++ b/postfix/src/global/scache_clnt.c @@ -112,7 +112,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, SCACHE_REQ_SAVE_ENDP, - ATTR_TYPE_NUM, MAIL_ATTR_TTL, endp_ttl, + ATTR_TYPE_INT, MAIL_ATTR_TTL, endp_ttl, ATTR_TYPE_STR, MAIL_ATTR_LABEL, endp_label, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, ATTR_TYPE_END) != 0 @@ -124,7 +124,7 @@ static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl, #endif || LOCAL_SEND_FD(vstream_fileno(stream), fd) < 0 || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", @@ -178,7 +178,7 @@ static int scache_clnt_find_endp(SCACHE *scache, const char *endp_label, ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, ATTR_TYPE_END) != 2) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) @@ -262,14 +262,14 @@ static void scache_clnt_save_dest(SCACHE *scache, int dest_ttl, errno = 0; if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, SCACHE_REQ_SAVE_DEST, - ATTR_TYPE_NUM, MAIL_ATTR_TTL, dest_ttl, + ATTR_TYPE_INT, MAIL_ATTR_TTL, dest_ttl, ATTR_TYPE_STR, MAIL_ATTR_LABEL, dest_label, ATTR_TYPE_STR, MAIL_ATTR_PROP, dest_prop, ATTR_TYPE_STR, MAIL_ATTR_LABEL, endp_label, ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", @@ -321,7 +321,7 @@ static int scache_clnt_find_dest(SCACHE *scache, const char *dest_label, ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_STR, MAIL_ATTR_PROP, dest_prop, ATTR_TYPE_STR, MAIL_ATTR_PROP, endp_prop, ATTR_TYPE_END) != 3) { diff --git a/postfix/src/global/trace.c b/postfix/src/global/trace.c index d6d30a098..e6e86ee06 100644 --- a/postfix/src/global/trace.c +++ b/postfix/src/global/trace.c @@ -121,8 +121,8 @@ int trace_append(int flags, const char *id, MSG_STATS *stats, my_dsn.reason = vstring_str(why); if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, @@ -145,14 +145,14 @@ int trace_flush(int flags, const char *queue, const char *id, const char *dsn_envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0) { return (0); } else { diff --git a/postfix/src/global/verify_clnt.c b/postfix/src/global/verify_clnt.c index 14dd3cd5e..916cce3fc 100644 --- a/postfix/src/global/verify_clnt.c +++ b/postfix/src/global/verify_clnt.c @@ -115,8 +115,8 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why) ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &request_status, - ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, addr_status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status, + ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, ATTR_TYPE_END) != 3) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) @@ -154,11 +154,11 @@ int verify_clnt_update(const char *addr, int addr_status, const char *why) if (attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_UPDATE, ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr, - ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, addr_status, + ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, ATTR_TYPE_END) != 0 || attr_scan(stream, ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &request_status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status, ATTR_TYPE_END) != 1) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", diff --git a/postfix/src/global/virtual8.in b/postfix/src/global/virtual8.in deleted file mode 100644 index d030a94e7..000000000 --- a/postfix/src/global/virtual8.in +++ /dev/null @@ -1,8 +0,0 @@ -aaa@domain.tld -aaa+xxx@domain.tld -bbb@domain.tld -bbb+yyy@domain.tld -ccc@domain.tld -ccc+zzz@domain.tld -aaa@domain.ttt -aaa+bbb@domain.ttt diff --git a/postfix/src/global/virtual8.ref b/postfix/src/global/virtual8.ref deleted file mode 100644 index 0e9c19c84..000000000 --- a/postfix/src/global/virtual8.ref +++ /dev/null @@ -1,8 +0,0 @@ -aaa@domain.tld -> aaa -aaa+xxx@domain.tld -> aaa -bbb@domain.tld -> bbb -bbb+yyy@domain.tld -> bbb -ccc@domain.tld -> catchall -ccc+zzz@domain.tld -> catchall -aaa@domain.ttt -> (none) -aaa+bbb@domain.ttt -> (none) diff --git a/postfix/src/global/virtual8_map b/postfix/src/global/virtual8_map deleted file mode 100644 index f0231d5e5..000000000 --- a/postfix/src/global/virtual8_map +++ /dev/null @@ -1,3 +0,0 @@ -@domain.tld catchall -aaa@domain.tld aaa -bbb@domain.tld bbb diff --git a/postfix/src/global/virtual8_maps.c b/postfix/src/global/virtual8_maps.c deleted file mode 100644 index fb05dc7d0..000000000 --- a/postfix/src/global/virtual8_maps.c +++ /dev/null @@ -1,163 +0,0 @@ -/*++ -/* NAME -/* virtual8_maps 3 -/* SUMMARY -/* virtual delivery agent map lookups -/* SYNOPSIS -/* #include -/* -/* MAPS *virtual8_maps_create(title, map_names, flags) -/* const char *title; -/* const char *map_names; -/* int flags; -/* -/* const char *virtual8_maps_find(maps, recipient) -/* MAPS *maps; -/* const char *recipient; -/* -/* MAPS *virtual8_maps_free(maps) -/* MAPS *maps; -/* DESCRIPTION -/* This module does user lookups for the virtual delivery -/* agent. The code is made available as a library module so that -/* other programs can perform compatible queries. -/* -/* Lookups are case sensitive. -/* -/* virtual8_maps_create() takes list of type:name pairs and opens the -/* named dictionaries. -/* The result is a handle that must be specified along with all -/* other virtual8_maps_xxx() operations. -/* See dict_open(3) for a description of flags. -/* -/* virtual8_maps_find() searches the specified list of dictionaries -/* in the specified order for the named key. The result is in -/* memory that is overwritten upon each call. -/* -/* virtual8_maps_free() releases storage claimed by virtual8_maps_create() -/* and conveniently returns a null pointer. -/* -/* Arguments: -/* .IP title -/* String used for diagnostics. Typically one specifies the -/* type of information stored in the lookup tables. -/* .IP map_names -/* Null-terminated string with type:name dictionary specifications, -/* separated by whitespace or commas. -/* .IP maps -/* A result from maps_create(). -/* .IP key -/* Null-terminated string with a lookup key. Table lookup is case -/* sensitive. -/* DIAGNOSTICS -/* The dict_errno variable is non-zero in case of problems. -/* BUGS -/* This code is a temporary solution that implements a hard-coded -/* lookup strategy. In a future version of Postfix, the lookup -/* strategy should become configurable. -/* SEE ALSO -/* virtual(8) virtual mailbox delivery agent -/* maps(3) multi-dictionary search -/* dict_open(3) low-level dictionary interface -/* 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 -#include - -/* Utility library. */ - -#include -#include - -/* Global library. */ - -#include -#include -#include -#include - -/* Application-specific. */ - -/* virtual8_maps_find - lookup for virtual delivery agent */ - -const char *virtual8_maps_find(MAPS *maps, const char *recipient) -{ - const char *ratsign; - const char *result; - char *bare = 0; - - /* - * Look up the address minus the optional extension. This is done first, - * to avoid hammering the database with extended address lookups, and to - * have straightforward semantics (extensions are always ignored). - */ - if (*var_rcpt_delim - && (bare = strip_addr(recipient, (char **) 0, *var_rcpt_delim)) != 0) { - result = maps_find(maps, bare, DICT_FLAG_FIXED); - myfree(bare); - if (result != 0 || dict_errno != 0) - return (result); - } - - /* - * Look up the full address. Allow regexp table searches. - */ - if (bare == 0) { - result = maps_find(maps, recipient, DICT_FLAG_NONE); - if (result != 0 || dict_errno != 0) - return (result); - } - - /* - * Look up the @domain catch-all. - */ - if ((ratsign = strrchr(recipient, '@')) == 0) - return (0); - return (maps_find(maps, ratsign, DICT_FLAG_FIXED)); -} - -#ifdef TEST - -#include -#include -#include - -#define STR(x) vstring_str(x) - -int main(int argc, char **argv) -{ - VSTRING *buffer; - MAPS *maps; - const char *result; - - if (argc != 2) - msg_fatal("usage: %s mapname", argv[0]); - - var_rcpt_delim = "+"; - var_double_bounce_sender = DEF_DOUBLE_BOUNCE; - - maps = virtual8_maps_create("testmap", argv[1], DICT_FLAG_LOCK); - buffer = vstring_alloc(1); - - while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { - result = virtual8_maps_find(maps, STR(buffer)); - vstream_printf("%s -> %s\n", STR(buffer), result ? result : "(none)"); - vstream_fflush(VSTREAM_OUT); - } - virtual8_maps_free(maps); - vstring_free(buffer); - return (0); -} - -#endif diff --git a/postfix/src/global/virtual8_maps.h b/postfix/src/global/virtual8_maps.h deleted file mode 100644 index 67c5df910..000000000 --- a/postfix/src/global/virtual8_maps.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _VIRTUAL8_MAPS_H_INCLUDED_ -#define _VIRTUAL8_MAPS_H_INCLUDED_ - -/*++ -/* NAME -/* virtual8_maps 3h -/* SUMMARY -/* virtual delivery agent compatibility -/* SYNOPSIS -/* #include -/* DESCRIPTION -/* .nf - - /* - * Global library. - */ -#include - - /* - * External interface. - */ -#define virtual8_maps_create(title, map_names, flags) \ - maps_create((title), (map_names), (flags)) -extern const char *virtual8_maps_find(MAPS *, const char *); -#define virtual8_maps_free(maps) maps_free((maps)) - -/* 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 -/*--*/ - -#endif diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c index 9ab147b27..4674b7e0b 100644 --- a/postfix/src/local/forward.c +++ b/postfix/src/local/forward.c @@ -145,7 +145,7 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender) #define FORWARD_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_INTERNAL) attr_print(cleanup, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, FORWARD_CLEANUP_FLAGS, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, FORWARD_CLEANUP_FLAGS, ATTR_TYPE_END); /* @@ -292,7 +292,7 @@ static int forward_send(FORWARD_INFO *info, DELIVER_REQUEST *request, if (status == 0) if (vstream_fflush(info->cleanup) || attr_scan(info->cleanup, ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) status = 1; diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index 759f71c34..ce793369a 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -833,7 +833,8 @@ static void pre_init(char *unused_name, char **unused_argv) set_file_limit(var_mailbox_limit); } alias_maps = maps_create("aliases", var_alias_maps, - DICT_FLAG_LOCK | DICT_FLAG_PARANOID); + DICT_FLAG_LOCK | DICT_FLAG_PARANOID + | DICT_FLAG_FOLD_FIX); flush_init(); } diff --git a/postfix/src/local/mailbox.c b/postfix/src/local/mailbox.c index fc2119a69..4b754caa7 100644 --- a/postfix/src/local/mailbox.c +++ b/postfix/src/local/mailbox.c @@ -270,10 +270,10 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) */ if (*var_mbox_transp_maps && transp_maps == 0) transp_maps = maps_create(VAR_MBOX_TRANSP_MAPS, var_mbox_transp_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB); if (*var_mbox_transp_maps && (map_transport = maps_find(transp_maps, state.msg_attr.user, - DICT_FLAG_FIXED)) != 0) { + DICT_FLAG_NONE)) != 0) { state.msg_attr.rcpt.offset = -1L; *statusp = deliver_pass(MAIL_CLASS_PRIVATE, map_transport, state.request, &state.msg_attr.rcpt); @@ -310,11 +310,11 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) if (*var_mailbox_cmd_maps && cmd_maps == 0) cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_PARANOID); if (*var_mailbox_cmd_maps && (map_command = maps_find(cmd_maps, state.msg_attr.user, - DICT_FLAG_FIXED)) != 0) { + DICT_FLAG_NONE)) != 0) { status = deliver_command(state, usr_attr, map_command); } else if (*var_mailbox_command) { status = deliver_command(state, usr_attr, var_mailbox_command); diff --git a/postfix/src/local/unknown.c b/postfix/src/local/unknown.c index c6d7ed9f0..4293c2f92 100644 --- a/postfix/src/local/unknown.c +++ b/postfix/src/local/unknown.c @@ -108,10 +108,10 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) */ if (*var_fbck_transp_maps && transp_maps == 0) transp_maps = maps_create(VAR_FBCK_TRANSP_MAPS, var_fbck_transp_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB); if (*var_fbck_transp_maps && (map_transport = maps_find(transp_maps, state.msg_attr.user, - DICT_FLAG_FIXED)) != 0) { + DICT_FLAG_NONE)) != 0) { return (deliver_pass(MAIL_CLASS_PRIVATE, map_transport, state.request, &state.msg_attr.rcpt)); } diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index d361b2c55..fd1ed8459 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -485,6 +485,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) char *oval; char *generation; int msg_vstream_needed = 0; + int privileged = 0; /* * Process environment options as early as we can. @@ -654,6 +655,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if (user_name) msg_fatal("service %s requires privileged operation", service_name); + privileged = 1; break; default: msg_panic("%s: unknown argument type: %d", myname, key); @@ -661,6 +663,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) } va_end(ap); + if (privileged == 0 && user_name == 0) + msg_fatal("service %s requires unprivileged operation", service_name); + if (root_dir) root_dir = var_queue_dir; if (user_name) diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index 6cfefa16c..bb01bce48 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -399,6 +399,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) char *oval; char *generation; int msg_vstream_needed = 0; + int privileged = 0; /* * Process environment options as early as we can. @@ -565,6 +566,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) if (user_name) msg_fatal("service %s requires privileged operation", service_name); + privileged = 1; break; default: msg_panic("%s: unknown argument type: %d", myname, key); @@ -572,6 +574,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) } va_end(ap); + if (privileged == 0 && user_name == 0) + msg_fatal("service %s requires unprivileged operation", service_name); + if (root_dir) root_dir = var_queue_dir; if (user_name) diff --git a/postfix/src/master/trigger_server.c b/postfix/src/master/trigger_server.c index b7e672429..9f686add4 100644 --- a/postfix/src/master/trigger_server.c +++ b/postfix/src/master/trigger_server.c @@ -405,6 +405,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. char *oval; char *generation; int msg_vstream_needed = 0; + int privileged = 0; /* * Process environment options as early as we can. @@ -571,6 +572,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. if (user_name) msg_fatal("service %s requires privileged operation", service_name); + privileged = 1; break; default: msg_panic("%s: unknown argument type: %d", myname, key); @@ -578,6 +580,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. } va_end(ap); + if (privileged == 0 && user_name == 0) + msg_fatal("service %s requires unprivileged operation", service_name); + if (root_dir) root_dir = var_queue_dir; if (user_name) diff --git a/postfix/src/oqmgr/qmgr_deliver.c b/postfix/src/oqmgr/qmgr_deliver.c index 1f813ce4d..356c844d4 100644 --- a/postfix/src/oqmgr/qmgr_deliver.c +++ b/postfix/src/oqmgr/qmgr_deliver.c @@ -93,7 +93,7 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream) msg_warn("%s: premature disconnect", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); } else if (attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 1) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); @@ -113,7 +113,7 @@ static int qmgr_deliver_final_reply(VSTREAM *stream, DSN_BUF *dsb) return (DELIVER_STAT_CRASH); } else if (attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_FUNC, dsb_scan, (void *) dsb, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 2) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); @@ -153,7 +153,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) | (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT); (void) QMGR_MSG_STATS(&stats, message); attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset, @@ -162,7 +162,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, message->dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, message->dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, message->dsn_ret, ATTR_TYPE_FUNC, msg_stats_print, (void *) &stats, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr, @@ -172,7 +172,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username, ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender, ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context, - ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, list.len, + ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, list.len, ATTR_TYPE_END); if (sender_buf != 0) vstring_free(sender_buf); diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 0a73ec66f..e6fcb5c50 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -380,7 +380,7 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, */ rec_fputs(cleanup, REC_TYPE_END, ""); if (attr_scan(cleanup, ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) return (cleanup_service_error(info, CLEANUP_STAT_WRITE)); @@ -445,7 +445,7 @@ static int pickup_file(PICKUP_INFO *info) ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf, ATTR_TYPE_END) != 1 || attr_print(cleanup, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) { status = KEEP_MESSAGE_FILE; } else { diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index 2fa055b11..a62d065f0 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -25,6 +25,15 @@ /* The format of Postfix alias input files is described in /* \fBaliases\fR(5). /* +/* By default the lookup key is mapped to lowercase to make +/* the lookups case insensitive; as of Postfix 2.3 this case +/* folding happens only with tables whose lookup keys are +/* fixed-case strings such as btree:, dbm: or hash:. With +/* earlier versions, the lookup key is folded even with tables +/* where a lookup field can match both upper and lower case +/* text, such as regexp: and pcre:. This resulted in loss of +/* information with $\fInumber\fR substitutions. +/* /* Options: /* .IP "\fB-c \fIconfig_dir\fR" /* Read the \fBmain.cf\fR configuration file in the named directory @@ -38,7 +47,7 @@ /* when at least one of the requested keys was found. /* .IP \fB-f\fR /* Do not fold the lookup key to lower case while creating or querying -/* a map. +/* a table. /* .IP \fB-i\fR /* Incremental mode. Read entries from standard input and do not /* truncate an existing database. By default, \fBpostalias\fR(1) creates @@ -358,8 +367,6 @@ static void postalias(char *map_type, char *path_name, int postalias_flags, /* * Store the value under a case-insensitive key. */ - if (dict_flags & DICT_FLAG_FOLD_KEY) - lowercase(STR(key_buffer)); mkmap_append(mkmap, STR(key_buffer), STR(value_buffer)); } @@ -434,13 +441,11 @@ static int postalias_queries(VSTREAM *in, char **maps, const int map_count, * maps. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { - if (dict_flags & DICT_FLAG_FOLD_KEY) - lowercase(STR(keybuf)); for (n = 0; n < map_count; n++) { if (dicts[n] == 0) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? - dict_open3(maps[n], map_name, O_RDONLY, DICT_FLAG_LOCK) : - dict_open3(var_db_type, maps[n], O_RDONLY, DICT_FLAG_LOCK)); + dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : + dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); if ((value = dict_get(dicts[n], STR(keybuf))) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", @@ -472,12 +477,12 @@ static int postalias_queries(VSTREAM *in, char **maps, const int map_count, /* postalias_query - query a map and print the result to stdout */ static int postalias_query(const char *map_type, const char *map_name, - const char *key) + const char *key, int dict_flags) { DICT *dict; const char *value; - dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK); + dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); if ((value = dict_get(dict, key)) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", @@ -494,7 +499,8 @@ static int postalias_query(const char *map_type, const char *map_name, /* postalias_deletes - apply multiple requests from stdin */ -static int postalias_deletes(VSTREAM *in, char **maps, const int map_count) +static int postalias_deletes(VSTREAM *in, char **maps, const int map_count, + int dict_flags) { int found = 0; VSTRING *keybuf = vstring_alloc(100); @@ -514,8 +520,8 @@ static int postalias_deletes(VSTREAM *in, char **maps, const int map_count) dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count); for (n = 0; n < map_count; n++) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? - dict_open3(maps[n], map_name, O_RDWR, DICT_FLAG_LOCK) : - dict_open3(var_db_type, maps[n], O_RDWR, DICT_FLAG_LOCK)); + dict_open3(maps[n], map_name, O_RDWR, dict_flags) : + dict_open3(var_db_type, maps[n], O_RDWR, dict_flags)); /* * Perform all requests. @@ -539,12 +545,12 @@ static int postalias_deletes(VSTREAM *in, char **maps, const int map_count) /* postalias_delete - delete a key value pair from a map */ static int postalias_delete(const char *map_type, const char *map_name, - const char *key) + const char *key, int dict_flags) { DICT *dict; int status; - dict = dict_open3(map_type, map_name, O_RDWR, DICT_FLAG_LOCK); + dict = dict_open3(map_type, map_name, O_RDWR, dict_flags); status = dict_del(dict, key); dict_close(dict); return (status == 0); @@ -552,14 +558,15 @@ static int postalias_delete(const char *map_type, const char *map_name, /* postalias_seq - print all map entries to stdout */ -static void postalias_seq(const char *map_type, const char *map_name) +static void postalias_seq(const char *map_type, const char *map_name, + int dict_flags) { DICT *dict; const char *key; const char *value; int func; - dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK); + dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) { if (dict_seq(dict, func, &key, &value) != 0) break; @@ -595,7 +602,7 @@ int main(int argc, char **argv) struct stat st; int postalias_flags = POSTALIAS_FLAG_AS_OWNER | POSTALIAS_FLAG_SAVE_PERM; int open_flags = O_RDWR | O_CREAT | O_TRUNC; - int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_KEY; + int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_FIX; char *query = 0; char *delkey = 0; int sequence = 0; @@ -654,7 +661,7 @@ int main(int argc, char **argv) delkey = optarg; break; case 'f': - dict_flags &= ~DICT_FLAG_FOLD_KEY; + dict_flags &= ~DICT_FLAG_FOLD_FIX; break; case 'i': open_flags &= ~O_TRUNC; @@ -703,13 +710,16 @@ int main(int argc, char **argv) if (optind + 1 > argc) usage(argv[0]); if (strcmp(delkey, "-") == 0) - exit(postalias_deletes(VSTREAM_IN, argv + optind, argc - optind) == 0); + exit(postalias_deletes(VSTREAM_IN, argv + optind, argc - optind, + dict_flags | DICT_FLAG_LOCK) == 0); found = 0; while (optind < argc) { if ((path_name = split_at(argv[optind], ':')) != 0) { - found |= postalias_delete(argv[optind], path_name, delkey); + found |= postalias_delete(argv[optind], path_name, delkey, + dict_flags | DICT_FLAG_LOCK); } else { - found |= postalias_delete(var_db_type, argv[optind], delkey); + found |= postalias_delete(var_db_type, argv[optind], delkey, + dict_flags | DICT_FLAG_LOCK); } optind++; } @@ -719,14 +729,14 @@ int main(int argc, char **argv) usage(argv[0]); if (strcmp(query, "-") == 0) exit(postalias_queries(VSTREAM_IN, argv + optind, argc - optind, - dict_flags) == 0); - if (dict_flags & DICT_FLAG_FOLD_KEY) - lowercase(query); + dict_flags | DICT_FLAG_LOCK) == 0); while (optind < argc) { if ((path_name = split_at(argv[optind], ':')) != 0) { - found = postalias_query(argv[optind], path_name, query); + found = postalias_query(argv[optind], path_name, query, + dict_flags | DICT_FLAG_LOCK); } else { - found = postalias_query(var_db_type, argv[optind], query); + found = postalias_query(var_db_type, argv[optind], query, + dict_flags | DICT_FLAG_LOCK); } if (found) exit(0); @@ -736,9 +746,11 @@ int main(int argc, char **argv) } else if (sequence) { while (optind < argc) { if ((path_name = split_at(argv[optind], ':')) != 0) { - postalias_seq(argv[optind], path_name); + postalias_seq(argv[optind], path_name, + dict_flags | DICT_FLAG_LOCK); } else { - postalias_seq(var_db_type, argv[optind]); + postalias_seq(var_db_type, argv[optind], + dict_flags | DICT_FLAG_LOCK); } exit(0); } diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 461369cc2..488753f60 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -456,7 +456,7 @@ int main(int argc, char **argv) * Send the completion status to the caller and terminate. */ attr_print(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_STR, MAIL_ATTR_WHY, "", ATTR_TYPE_END); vstream_fflush(VSTREAM_OUT); diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index ef6ebcda6..bc9e2bd8f 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -42,8 +42,16 @@ /* The \fIkey\fR and \fIvalue\fR are processed as is, except that /* surrounding white space is stripped off. Unlike with Postfix alias /* databases, quotes cannot be used to protect lookup keys that contain -/* special characters such as `#' or whitespace. The \fIkey\fR is mapped -/* to lowercase to make mapping lookups case insensitive. +/* special characters such as `#' or whitespace. +/* +/* By default the lookup key is mapped to lowercase to make +/* the lookups case insensitive; as of Postfix 2.3 this case +/* folding happens only with tables whose lookup keys are +/* fixed-case strings such as btree:, dbm: or hash:. With +/* earlier versions, the lookup key is folded even with tables +/* where a lookup field can match both upper and lower case +/* text, such as regexp: and pcre:. This resulted in loss of +/* information with $\fInumber\fR substitutions. /* COMMAND-LINE ARGUMENTS /* .ad /* .fi @@ -59,7 +67,7 @@ /* when at least one of the requested keys was found. /* .IP \fB-f\fR /* Do not fold the lookup key to lower case while creating or querying -/* a map. +/* a table. /* .IP \fB-i\fR /* Incremental mode. Read entries from standard input and do not /* truncate an existing database. By default, \fBpostmap\fR(1) creates @@ -333,8 +341,6 @@ static void postmap(char *map_type, char *path_name, int postmap_flags, /* * Store the value under a case-insensitive key. */ - if (dict_flags & DICT_FLAG_FOLD_KEY) - lowercase(key); mkmap_append(mkmap, key, value); } @@ -381,13 +387,11 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count, * maps. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { - if (dict_flags & DICT_FLAG_FOLD_KEY) - lowercase(STR(keybuf)); for (n = 0; n < map_count; n++) { if (dicts[n] == 0) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? - dict_open3(maps[n], map_name, O_RDONLY, DICT_FLAG_LOCK) : - dict_open3(var_db_type, maps[n], O_RDONLY, DICT_FLAG_LOCK)); + dict_open3(maps[n], map_name, O_RDONLY, dict_flags) : + dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags)); if ((value = dict_get(dicts[n], STR(keybuf))) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", @@ -419,12 +423,12 @@ static int postmap_queries(VSTREAM *in, char **maps, const int map_count, /* postmap_query - query a map and print the result to stdout */ static int postmap_query(const char *map_type, const char *map_name, - const char *key) + const char *key, int dict_flags) { DICT *dict; const char *value; - dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK); + dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); if ((value = dict_get(dict, key)) != 0) { if (*value == 0) { msg_warn("table %s:%s: key %s: empty string result is not allowed", @@ -441,7 +445,8 @@ static int postmap_query(const char *map_type, const char *map_name, /* postmap_deletes - apply multiple requests from stdin */ -static int postmap_deletes(VSTREAM *in, char **maps, const int map_count) +static int postmap_deletes(VSTREAM *in, char **maps, const int map_count, + int dict_flags) { int found = 0; VSTRING *keybuf = vstring_alloc(100); @@ -461,8 +466,8 @@ static int postmap_deletes(VSTREAM *in, char **maps, const int map_count) dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count); for (n = 0; n < map_count; n++) dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ? - dict_open3(maps[n], map_name, O_RDWR, DICT_FLAG_LOCK) : - dict_open3(var_db_type, maps[n], O_RDWR, DICT_FLAG_LOCK)); + dict_open3(maps[n], map_name, O_RDWR, dict_flags) : + dict_open3(var_db_type, maps[n], O_RDWR, dict_flags)); /* * Perform all requests. @@ -486,12 +491,12 @@ static int postmap_deletes(VSTREAM *in, char **maps, const int map_count) /* postmap_delete - delete a (key, value) pair from a map */ static int postmap_delete(const char *map_type, const char *map_name, - const char *key) + const char *key, int dict_flags) { DICT *dict; int status; - dict = dict_open3(map_type, map_name, O_RDWR, DICT_FLAG_LOCK); + dict = dict_open3(map_type, map_name, O_RDWR, dict_flags); status = dict_del(dict, key); dict_close(dict); return (status == 0); @@ -499,14 +504,15 @@ static int postmap_delete(const char *map_type, const char *map_name, /* postmap_seq - print all map entries to stdout */ -static void postmap_seq(const char *map_type, const char *map_name) +static void postmap_seq(const char *map_type, const char *map_name, + int dict_flags) { DICT *dict; const char *key; const char *value; int func; - dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK); + dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) { if (dict_seq(dict, func, &key, &value) != 0) break; @@ -542,7 +548,7 @@ int main(int argc, char **argv) struct stat st; int postmap_flags = POSTMAP_FLAG_AS_OWNER | POSTMAP_FLAG_SAVE_PERM; int open_flags = O_RDWR | O_CREAT | O_TRUNC; - int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_KEY; + int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_FIX; char *query = 0; char *delkey = 0; int sequence = 0; @@ -601,7 +607,7 @@ int main(int argc, char **argv) delkey = optarg; break; case 'f': - dict_flags &= ~DICT_FLAG_FOLD_KEY; + dict_flags &= ~DICT_FLAG_FOLD_FIX; break; case 'i': open_flags &= ~O_TRUNC; @@ -650,13 +656,16 @@ int main(int argc, char **argv) if (optind + 1 > argc) usage(argv[0]); if (strcmp(delkey, "-") == 0) - exit(postmap_deletes(VSTREAM_IN, argv + optind, argc - optind) == 0); + exit(postmap_deletes(VSTREAM_IN, argv + optind, argc - optind, + dict_flags | DICT_FLAG_LOCK) == 0); found = 0; while (optind < argc) { if ((path_name = split_at(argv[optind], ':')) != 0) { - found |= postmap_delete(argv[optind], path_name, delkey); + found |= postmap_delete(argv[optind], path_name, delkey, + dict_flags | DICT_FLAG_LOCK); } else { - found |= postmap_delete(var_db_type, argv[optind], delkey); + found |= postmap_delete(var_db_type, argv[optind], delkey, + dict_flags | DICT_FLAG_LOCK); } optind++; } @@ -666,14 +675,14 @@ int main(int argc, char **argv) usage(argv[0]); if (strcmp(query, "-") == 0) exit(postmap_queries(VSTREAM_IN, argv + optind, argc - optind, - dict_flags) == 0); - if (dict_flags & DICT_FLAG_FOLD_KEY) - lowercase(query); + dict_flags | DICT_FLAG_LOCK) == 0); while (optind < argc) { if ((path_name = split_at(argv[optind], ':')) != 0) { - found = postmap_query(argv[optind], path_name, query); + found = postmap_query(argv[optind], path_name, query, + dict_flags | DICT_FLAG_LOCK); } else { - found = postmap_query(var_db_type, argv[optind], query); + found = postmap_query(var_db_type, argv[optind], query, + dict_flags | DICT_FLAG_LOCK); } if (found) exit(0); @@ -683,9 +692,11 @@ int main(int argc, char **argv) } else if (sequence) { while (optind < argc) { if ((path_name = split_at(argv[optind], ':')) != 0) { - postmap_seq(argv[optind], path_name); + postmap_seq(argv[optind], path_name, + dict_flags | DICT_FLAG_LOCK); } else { - postmap_seq(var_db_type, argv[optind]); + postmap_seq(var_db_type, argv[optind], + dict_flags | DICT_FLAG_LOCK); } exit(0); } diff --git a/postfix/src/postqueue/Makefile.in b/postfix/src/postqueue/Makefile.in index 49bc5f5f5..8b331ecc1 100644 --- a/postfix/src/postqueue/Makefile.in +++ b/postfix/src/postqueue/Makefile.in @@ -62,6 +62,7 @@ postqueue.o: ../../include/connect.h postqueue.o: ../../include/flush_clnt.h postqueue.o: ../../include/iostuff.h postqueue.o: ../../include/mail_conf.h +postqueue.o: ../../include/mail_dict.h postqueue.o: ../../include/mail_flush.h postqueue.o: ../../include/mail_params.h postqueue.o: ../../include/mail_proto.h diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index 44b377bad..9bfd2a265 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -190,6 +190,7 @@ #include #include #include +#include /* Application-specific. */ diff --git a/postfix/src/proxymap/proxymap.c b/postfix/src/proxymap/proxymap.c index e1ffd7e54..7b9326a55 100644 --- a/postfix/src/proxymap/proxymap.c +++ b/postfix/src/proxymap/proxymap.c @@ -238,8 +238,8 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags, /* * Open one instance of a map for each combination of name+flags. */ - vstring_sprintf(map_type_name_flags, "%s:%o", - map_type_name, request_flags); + vstring_sprintf(map_type_name_flags, "%s:%s", + map_type_name, dict_flags_str(request_flags)); if ((dict = dict_handle(STR(map_type_name_flags))) == 0) dict = dict_open(map_type_name, READ_OPEN_FLAGS, request_flags); if (dict == 0) @@ -262,7 +262,7 @@ static void proxymap_lookup_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_TABLE, request_map, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &request_flags, ATTR_TYPE_STR, MAIL_ATTR_KEY, request_key, ATTR_TYPE_END) != 3) { reply_status = PROXY_STAT_BAD; @@ -284,7 +284,7 @@ static void proxymap_lookup_service(VSTREAM *client_stream) * Respond to the client. */ attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, reply_status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, reply_status, ATTR_TYPE_STR, MAIL_ATTR_VALUE, reply_value, ATTR_TYPE_END); } @@ -303,7 +303,7 @@ static void proxymap_open_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_TABLE, request_map, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &request_flags, ATTR_TYPE_END) != 2) { reply_status = PROXY_STAT_BAD; reply_flags = 0; @@ -319,8 +319,8 @@ static void proxymap_open_service(VSTREAM *client_stream) * Respond to the client. */ attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, reply_status, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, reply_flags, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, reply_status, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, reply_flags, ATTR_TYPE_END); } @@ -352,7 +352,7 @@ static void proxymap_service(VSTREAM *client_stream, char *unused_service, } else { msg_warn("unrecognized request: \"%s\", ignored", STR(request)); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, PROXY_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, PROXY_STAT_BAD, ATTR_TYPE_END); } } diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index 9dc54c2f5..59ae7f102 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -98,7 +98,7 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream) msg_warn("%s: premature disconnect", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); } else if (attr_scan(stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 1) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); @@ -118,7 +118,7 @@ static int qmgr_deliver_final_reply(VSTREAM *stream, DSN_BUF *dsb) return (DELIVER_STAT_CRASH); } else if (attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_FUNC, dsb_scan, (void *) dsb, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, &stat, ATTR_TYPE_END) != 2) { msg_warn("%s: malformed response", VSTREAM_PATH(stream)); return (DELIVER_STAT_CRASH); @@ -158,7 +158,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) | (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT); (void) QMGR_MSG_STATS(&stats, message); attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset, @@ -167,7 +167,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, message->dsn_envid, - ATTR_TYPE_NUM, MAIL_ATTR_DSN_RET, message->dsn_ret, + ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, message->dsn_ret, ATTR_TYPE_FUNC, msg_stats_print, (void *) &stats, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_NAME, message->client_name, ATTR_TYPE_STR, MAIL_ATTR_CLIENT_ADDR, message->client_addr, @@ -177,7 +177,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username, ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender, ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context, - ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, list.len, + ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, list.len, ATTR_TYPE_END); if (sender_buf != 0) vstring_free(sender_buf); diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index bb8a5ab4f..ee45281bc 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -235,7 +235,7 @@ static void qmqpd_open_file(QMQPD_STATE *state) state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); diff --git a/postfix/src/scache/scache.c b/postfix/src/scache/scache.c index 86e17f459..9d2b0dbb7 100644 --- a/postfix/src/scache/scache.c +++ b/postfix/src/scache/scache.c @@ -219,14 +219,14 @@ static void scache_save_endp_service(VSTREAM *client_stream) if (attr_scan(client_stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_TTL, &ttl, + ATTR_TYPE_INT, MAIL_ATTR_TTL, &ttl, ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_endp_label, ATTR_TYPE_STR, MAIL_ATTR_PROP, scache_endp_prop, ATTR_TYPE_END) != 3 || ttl <= 0) { msg_warn("%s: bad or missing request parameter", myname); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, ATTR_TYPE_END); return; } else if ( @@ -242,7 +242,7 @@ static void scache_save_endp_service(VSTREAM *client_stream) (fd = LOCAL_RECV_FD(vstream_fileno(client_stream))) < 0) { msg_warn("%s: unable to receive file descriptor: %m", myname); (void) attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, ATTR_TYPE_END); return; } else { @@ -250,7 +250,7 @@ static void scache_save_endp_service(VSTREAM *client_stream) ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl, STR(scache_endp_label), STR(scache_endp_prop), fd); (void) attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_OK, ATTR_TYPE_END); scache_size(scache, &size); if (size.endp_count > scache_endp_count) @@ -274,21 +274,21 @@ static void scache_find_endp_service(VSTREAM *client_stream) ATTR_TYPE_END) != 1) { msg_warn("%s: bad or missing request parameter", myname); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, ATTR_TYPE_STR, MAIL_ATTR_PROP, "", ATTR_TYPE_END); return; } else if ((fd = scache_find_endp(scache, STR(scache_endp_label), scache_endp_prop)) < 0) { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, ATTR_TYPE_STR, MAIL_ATTR_PROP, "", ATTR_TYPE_END); scache_endp_miss++; return; } else { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_OK, ATTR_TYPE_STR, MAIL_ATTR_PROP, STR(scache_endp_prop), ATTR_TYPE_END); if (vstream_fflush(client_stream) != 0 @@ -322,7 +322,7 @@ static void scache_save_dest_service(VSTREAM *client_stream) if (attr_scan(client_stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_TTL, &ttl, + ATTR_TYPE_INT, MAIL_ATTR_TTL, &ttl, ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_dest_label, ATTR_TYPE_STR, MAIL_ATTR_PROP, scache_dest_prop, ATTR_TYPE_STR, MAIL_ATTR_LABEL, scache_endp_label, @@ -330,7 +330,7 @@ static void scache_save_dest_service(VSTREAM *client_stream) || ttl <= 0) { msg_warn("%s: bad or missing request parameter", myname); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, ATTR_TYPE_END); return; } else { @@ -339,7 +339,7 @@ static void scache_save_dest_service(VSTREAM *client_stream) STR(scache_dest_label), STR(scache_dest_prop), STR(scache_endp_label)); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_OK, ATTR_TYPE_END); scache_size(scache, &size); if (size.dest_count > scache_dest_count) @@ -363,7 +363,7 @@ static void scache_find_dest_service(VSTREAM *client_stream) ATTR_TYPE_END) != 1) { msg_warn("%s: bad or missing request parameter", myname); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, ATTR_TYPE_STR, MAIL_ATTR_PROP, "", ATTR_TYPE_STR, MAIL_ATTR_PROP, "", ATTR_TYPE_END); @@ -372,7 +372,7 @@ static void scache_find_dest_service(VSTREAM *client_stream) scache_dest_prop, scache_endp_prop)) < 0) { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_FAIL, ATTR_TYPE_STR, MAIL_ATTR_PROP, "", ATTR_TYPE_STR, MAIL_ATTR_PROP, "", ATTR_TYPE_END); @@ -380,7 +380,7 @@ static void scache_find_dest_service(VSTREAM *client_stream) return; } else { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_OK, ATTR_TYPE_STR, MAIL_ATTR_PROP, STR(scache_dest_prop), ATTR_TYPE_STR, MAIL_ATTR_PROP, STR(scache_endp_prop), ATTR_TYPE_END); @@ -446,7 +446,7 @@ static void scache_service(VSTREAM *client_stream, char *unused_service, msg_warn("unrecognized request: \"%s\", ignored", STR(scache_request)); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, SCACHE_STAT_BAD, ATTR_TYPE_END); } } diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 88a5b6807..3bf1a67e4 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -91,7 +91,7 @@ /* parent directory. This information is ignored with Postfix /* versions before 2.3. /* -/* With older Postfix versions, specify a directory pathname +/* With all Postfix versions, you can specify a directory pathname /* with the MAIL_CONFIG environment variable to override the /* location of configuration files. /* .IP "\fB-F \fIfull_name\fR @@ -321,8 +321,8 @@ /* .IP "\fBenable_errors_to (no)\fR" /* Report mail delivery errors to the address specified with the /* non-standard Errors-To: message header, instead of the envelope -/* sender address (this feature is removed with Postfix 2.2, is -/* turned off by default with Postfix 2.1, and is always turned on +/* sender address (this feature is removed with Postfix version 2.2, is +/* turned off by default with Postfix version 2.1, and is always turned on /* with older Postfix versions). /* .IP "\fBmail_owner (postfix)\fR" /* The UNIX system account that owns the Postfix queue and most Postfix diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 668daea67..1ad8c3690 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -9,7 +9,7 @@ HDRS = smtp.h smtp_sasl.h smtp_addr.h smtp_reuse.h TESTSRC = DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) -TESTPROG= smtp_unalias smtp_map11 +TESTPROG= smtp_unalias smtp_map11 legacy levels PROG = smtp INC_DIR = ../../include LIBS = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \ @@ -63,6 +63,12 @@ smtp_unalias: smtp_unalias.c $(LIBS) smtp_map11: smtp_map11.c $(LIBS) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS) +legacy: legacy.c $(LIBS) + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) + +levels: levels.c $(LIBS) + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) + # This needs trivial-rewrite service and myorigin==mydomain smtp_map11_test: smtp_map11 map11_map smtp_map11.ref ../postmap/postmap map11_map diff --git a/postfix/src/smtp/legacy.c b/postfix/src/smtp/legacy.c new file mode 100644 index 000000000..867d02ce9 --- /dev/null +++ b/postfix/src/smtp/legacy.c @@ -0,0 +1,205 @@ + /* + * The old legacy TLS per-site policy engine, implemented with multiple + * boolean variables, stripped down for exhaustive comparison with the new + * legacy policy engine. + */ +/* System library. */ + +#include +#include +#include + +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + +/* Utility library. */ + +#include +#include +#include +#include + + /* + * Global policy variables. + */ +int var_smtp_enforce_tls; +int var_smtp_tls_enforce_peername; +int var_smtp_use_tls; + + /* + * Simplified session structure. + */ +typedef struct { + int tls_use_tls; + int tls_enforce_tls; + int tls_enforce_peername; +} SMTP_SESSION; + + /* + * Per-site policies can override main.cf settings. + */ +typedef struct { + int dont_use; /* don't use TLS */ + int use; /* useless, see above */ + int enforce; /* must always use TLS */ + int enforce_peername; /* must verify certificate name */ +} SMTP_TLS_SITE_POLICY; + +/* smtp_tls_site_policy - look up per-site TLS policy */ + +static void smtp_tls_site_policy(SMTP_TLS_SITE_POLICY *policy, + const char *lookup) +{ + + /* + * Initialize the default policy. + */ + policy->dont_use = 0; + policy->use = 0; + policy->enforce = 0; + policy->enforce_peername = 0; + + /* + * Look up a non-default policy. + */ + if (strcasecmp(lookup, "-")) { + if (!strcasecmp(lookup, "NONE")) + policy->dont_use = 1; + else if (!strcasecmp(lookup, "MAY")) + policy->use = 1; + else if (!strcasecmp(lookup, "MUST")) + policy->enforce = policy->enforce_peername = 1; + else if (!strcasecmp(lookup, "MUST_NOPEERMATCH")) + policy->enforce = 1; + else + msg_fatal("unknown TLS policy '%s'", lookup); + } +} + +static void policy(SMTP_SESSION *session, const char *host, const char *dest) +{ + SMTP_TLS_SITE_POLICY host_policy; + SMTP_TLS_SITE_POLICY rcpt_policy; + + session->tls_use_tls = session->tls_enforce_tls = 0; + session->tls_enforce_peername = 0; + + /* + * Override the main.cf TLS policy with an optional per-site policy. + */ + smtp_tls_site_policy(&host_policy, host); + smtp_tls_site_policy(&rcpt_policy, dest); + + /* + * Fix 200601: a combined per-site (NONE + MAY) policy changed global + * MUST into NONE, and all weaker global policies into MAY. This was + * discovered with exhaustive simulation. Fix verified by comparing + * exhaustive simulation results with Postfix 2.3 which re-implements + * per-site policies from the ground up. + */ +#ifdef FIX200601 + if ((host_policy.dont_use || rcpt_policy.dont_use) + && (host_policy.use || rcpt_policy.use)) { + host_policy.use = rcpt_policy.use = 0; + host_policy.dont_use = rcpt_policy.dont_use = 1; + } +#endif + + /* + * Set up TLS enforcement for this session. + */ + if ((var_smtp_enforce_tls && !host_policy.dont_use && !rcpt_policy.dont_use) + || host_policy.enforce || rcpt_policy.enforce) + session->tls_enforce_tls = session->tls_use_tls = 1; + + /* + * Set up peername checking for this session. + * + * We want to make sure that a MUST* entry in the tls_per_site table always + * has precedence. MUST always must lead to a peername check, + * MUST_NOPEERMATCH must always disable it. Only when no explicit setting + * has been found, the default will be used. + * + * Fix 200601: a per-site MUST_NOPEERMATCH policy could not override a + * global MUST policy. Fix verified by comparing exhaustive simulation + * results with Postfix 2.3 which re-implements per-site policy from the + * ground up. + */ + if (host_policy.enforce && host_policy.enforce_peername) + session->tls_enforce_peername = 1; + else if (rcpt_policy.enforce && rcpt_policy.enforce_peername) + session->tls_enforce_peername = 1; + else if ( +#ifdef FIX200601 + !host_policy.enforce && !rcpt_policy.enforce && /* Fix 200601 */ +#endif + var_smtp_enforce_tls && var_smtp_tls_enforce_peername) + session->tls_enforce_peername = 1; + else if ((var_smtp_use_tls && !host_policy.dont_use && !rcpt_policy.dont_use) || host_policy.use || rcpt_policy.use) + session->tls_use_tls = 1; +} + +static void set_global_policy(const char *global) +{ + var_smtp_tls_enforce_peername = var_smtp_enforce_tls = var_smtp_use_tls = 0; + + if (strcasecmp(global, "must") == 0) { + var_smtp_enforce_tls = 1; /* XXX */ + var_smtp_tls_enforce_peername = 1; + } else if (strcasecmp(global, "must_nopeermatch") == 0) { + var_smtp_enforce_tls = 1; + } else if (strcasecmp(global, "may") == 0) { + var_smtp_use_tls = 1; + } else if (strcasecmp(global, "-") !=0) { + msg_fatal("unknown global policy: %s", global); + } +} + +static const char *print_policy(SMTP_SESSION *session) +{ + if (session->tls_enforce_peername && session->tls_enforce_tls) + return ("must"); + if (session->tls_enforce_tls) + return ("must_nopeermatch"); + if (session->tls_use_tls) + return ("may"); + return ("none"); +} + +int main(int argc, char **argv) +{ + SMTP_SESSION session; + VSTRING *buf = vstring_alloc(200); + char *cp; + const char *global; + const char *host; + const char *dest; + const char *result; + const char *sep = " \t\r\n"; + + vstream_printf("%-20s %-20s %-20s %s\n", + "host", "dest", "global", "result"); + while (vstring_get_nonl(buf, VSTREAM_IN) >= 0) { + cp = vstring_str(buf); + if (*cp == 0 || *cp == '#') { + vstream_printf("%s\n", cp); + } else { + if ((host = mystrtok(&cp, sep)) == 0) + msg_fatal("missing host policy"); + if ((dest = mystrtok(&cp, sep)) == 0) + msg_fatal("missing nexthop policy"); + if ((global = mystrtok(&cp, sep)) == 0) + msg_fatal("missing global policy"); + if (mystrtok(&cp, sep) != 0) + msg_fatal("garbage after global policy"); + set_global_policy(global); + policy(&session, host, dest); + result = print_policy(&session); + vstream_printf("%-20s %-20s %-20s %s\n", + host, dest, global, result); + } + vstream_fflush(VSTREAM_OUT); + } + exit(0); +} diff --git a/postfix/src/smtp/levels.c b/postfix/src/smtp/levels.c new file mode 100644 index 000000000..e0baa460b --- /dev/null +++ b/postfix/src/smtp/levels.c @@ -0,0 +1,189 @@ + /* + * The new legacy TLS per-site policy engine, re-implemented in terms of + * enforcement levels, stripped down for exhaustive comparisons with the old + * legacy policy engine. + * + * This is the code that will be used in Postfix 2.3 so that sites can upgrade + * Postfix without being forced to change to the new TLS policy model. + */ + +/* System library. */ + +#include +#include +#include + +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + +/* Utility library. */ + +#include +#include +#include +#include + + /* + * Application-specific. + */ +#include + + /* + * Global policy variables. + */ +int var_smtp_enforce_tls; +int var_smtp_tls_enforce_peername; +int var_smtp_use_tls; + +/* smtp_tls_policy_lookup - look up per-site TLS policy */ + +static void smtp_tls_policy_lookup(int *site_level, const char *lookup) +{ + + /* + * Look up a non-default policy. In case of multiple lookup results, the + * precedence order is a permutation of the TLS enforcement level order: + * VERIFY, ENCRYPT, NONE, MAY, NOTFOUND. I.e. we override MAY with a more + * specific policy including NONE, otherwise we choose the stronger + * enforcement level. + */ + if (strcasecmp(lookup, "-")) { + if (!strcasecmp(lookup, "NONE")) { + /* NONE overrides MAY or NOTFOUND. */ + if (*site_level <= SMTP_TLS_LEV_MAY) + *site_level = SMTP_TLS_LEV_NONE; + } else if (!strcasecmp(lookup, "MAY")) { + /* MAY overrides NOTFOUND but not NONE. */ + if (*site_level < SMTP_TLS_LEV_NONE) + *site_level = SMTP_TLS_LEV_MAY; + } else if (!strcasecmp(lookup, "MUST_NOPEERMATCH")) { + if (*site_level < SMTP_TLS_LEV_ENCRYPT) + *site_level = SMTP_TLS_LEV_ENCRYPT; + } else if (!strcasecmp(lookup, "MUST")) { + if (*site_level < SMTP_TLS_LEV_VERIFY) + *site_level = SMTP_TLS_LEV_VERIFY; + } else { + msg_fatal("unknown TLS policy '%s'", lookup); + } + } +} + +static int policy(const char *host, const char *dest) +{ + int global_level; + int site_level; + int tls_level; + + /* + * Compute the global TLS policy. This is the default policy level when + * no per-site policy exists. It also is used to override a wild-card + * per-site policy. + */ + if (var_smtp_enforce_tls) + global_level = var_smtp_tls_enforce_peername ? + SMTP_TLS_LEV_VERIFY : SMTP_TLS_LEV_ENCRYPT; + else + global_level = var_smtp_use_tls ? + SMTP_TLS_LEV_MAY : SMTP_TLS_LEV_NONE; + + /* + * Compute the per-site TLS enforcement level. For compatibility with the + * original TLS patch, this algorithm is gives equal precedence to host + * and next-hop policies. + */ + site_level = SMTP_TLS_LEV_NOTFOUND; + + smtp_tls_policy_lookup(&site_level, dest); + smtp_tls_policy_lookup(&site_level, host); + + /* + * Override a wild-card per-site policy with a more specific global + * policy. + * + * With the original TLS patch, 1) a per-site ENCRYPT could not override a + * global VERIFY, and 2) a combined per-site (NONE+MAY) policy produced + * inconsistent results: it changed a global VERIFY into NONE, while + * producing MAY with all weaker global policy settings. + * + * With the current implementation, a combined per-site (NONE+MAY) + * consistently overrides global policy with NONE, and global policy can + * override only a per-site MAY wildcard. That is, specific policies + * consistently override wildcard policies, and (non-wildcard) per-site + * policies consistently override global policies. + */ + if (site_level == SMTP_TLS_LEV_NOTFOUND + || (site_level == SMTP_TLS_LEV_MAY + && global_level > SMTP_TLS_LEV_MAY)) + tls_level = global_level; + else + tls_level = site_level; + + return (tls_level); +} + +static void set_global_policy(const char *global) +{ + var_smtp_tls_enforce_peername = var_smtp_enforce_tls = var_smtp_use_tls = 0; + + if (strcasecmp(global, "must") == 0) { + var_smtp_enforce_tls = 1; /* XXX */ + var_smtp_tls_enforce_peername = 1; + } else if (strcasecmp(global, "must_nopeermatch") == 0) { + var_smtp_enforce_tls = 1; + } else if (strcasecmp(global, "may") == 0) { + var_smtp_use_tls = 1; + } else if (strcasecmp(global, "-") !=0) { + msg_fatal("unknown global policy: %s", global); + } +} + +static const char *print_policy(int level) +{ + if (level == SMTP_TLS_LEV_VERIFY) + return ("must"); + if (level == SMTP_TLS_LEV_ENCRYPT) + return ("must_nopeermatch"); + if (level == SMTP_TLS_LEV_MAY) + return ("may"); + if (level == SMTP_TLS_LEV_NONE) + return ("none"); + msg_panic("unknown policy level %d", level); +} + +int main(int argc, char **argv) +{ + VSTRING *buf = vstring_alloc(200); + char *cp; + const char *global; + const char *host; + const char *dest; + const char *result; + const char *sep = " \t\r\n"; + int level; + + vstream_printf("%-20s %-20s %-20s %s\n", + "host", "dest", "global", "result"); + while (vstring_get_nonl(buf, VSTREAM_IN) > 0) { + cp = vstring_str(buf); + if (*cp == 0 || *cp == '#') { + vstream_printf("%s\n", cp); + } else { + if ((host = mystrtok(&cp, sep)) == 0) + msg_fatal("missing host policy"); + if ((dest = mystrtok(&cp, sep)) == 0) + msg_fatal("missing nexthop policy"); + if ((global = mystrtok(&cp, sep)) == 0) + msg_fatal("missing global policy"); + if (mystrtok(&cp, sep) != 0) + msg_fatal("garbage after global policy"); + set_global_policy(global); + level = policy(host, dest); + result = print_policy(level); + vstream_printf("%-20s %-20s %-20s %s\n", + host, dest, global, result); + } + vstream_fflush(VSTREAM_OUT); + } + exit(0); +} diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index a05bc8ae2..ee00bb0ac 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -822,7 +822,7 @@ static void pre_init(char *unused_name, char **unused_argv) if (*var_smtp_generic_maps) smtp_generic_maps = maps_create(VAR_SMTP_GENERIC_MAPS, var_smtp_generic_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); } /* pre_accept - see if tables have changed */ diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index e79832fb0..4ec7dc55a 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -142,6 +142,22 @@ typedef struct SMTP_STATE { #define SMTP_MISC_FLAG_FINAL_SERVER (1<<5) #define SMTP_MISC_FLAG_CONN_CACHE (1<<6) + /* + * TLS enforcement level. Actual TLS policies will be NONE or higher. + * + * There are two pseudo levels: NOTFOUND is a sentinel value for the ease of + * implementation; MAY is a wild-card that indicates "anything goes". + * + * Non pseudo levels can also be used to indicate the actual security level of + * a session. + */ +#define SMTP_TLS_LEV_NOTFOUND (-1) /* sentinel */ +#define SMTP_TLS_LEV_NONE 0 /* plain-text only */ +#define SMTP_TLS_LEV_MAY 1 /* wildcard */ +#define SMTP_TLS_LEV_ENCRYPT 2 /* encrypted connection */ +#define SMTP_TLS_LEV_VERIFY 3 /* certificate verified */ +#define SMTP_TLS_LEV_STRICT 4 /* "secure" verification */ + /* * smtp.c */ @@ -215,9 +231,7 @@ typedef struct SMTP_SESSION { * TLS related state. */ #ifdef USE_TLS - int tls_use_tls; /* can do TLS */ - int tls_enforce_tls; /* must do TLS */ - int tls_enforce_peername; /* cert must match */ + int tls_level; /* TLS enforcement level */ TLScontext_t *tls_context; /* TLS session state */ #endif diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c index bb9f0d147..406b2aa1f 100644 --- a/postfix/src/smtp/smtp_addr.c +++ b/postfix/src/smtp/smtp_addr.c @@ -21,7 +21,7 @@ /* lookups are done via the Internet domain name service (DNS). /* A reasonable number of CNAME indirections is permitted. When /* DNS lookups are disabled, host address lookup is done with -/* gethostbyname(). +/* getnameinfo() or gethostbyname(). /* /* smtp_domain_addr() looks up the network addresses for mail /* exchanger hosts listed for the named domain. Addresses are diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index 8142cc47a..495c544a7 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -14,8 +14,8 @@ /* /* smtp_connect() attempts to establish an SMTP/LMTP session with a host /* that represents the destination domain, or with an optional fallback -/* relay when the destination cannot be found, or when all the -/* destination servers are unavailable. It skips over IP addresses +/* relay when {the destination cannot be found, or when all the +/* destination servers are unavailable}. It skips over IP addresses /* that fail to complete the SMTP/LMTP handshake and tries to find /* an alternate server when an SMTP/LMTP session fails to deliver. /* @@ -28,7 +28,7 @@ /* destinations may be specified as "unix:pathname", "inet:host" /* or "inet:host:port". /* -/* By default, the Internet domain name service is queried for mail +/* With SMTP, the Internet domain name service is queried for mail /* exchanger hosts. Quote the domain name with `[' and `]' to /* suppress mail exchanger lookups. /* diff --git a/postfix/src/smtp/smtp_map11.c b/postfix/src/smtp/smtp_map11.c index 297dee8a0..23b2937e0 100644 --- a/postfix/src/smtp/smtp_map11.c +++ b/postfix/src/smtp/smtp_map11.c @@ -143,7 +143,7 @@ int main(int argc, char **argv) if (argc < 3) msg_fatal("usage: %s maptype:mapname address...", argv[0]); - maps = maps_create(argv[1], argv[1], 0); + maps = maps_create(argv[1], argv[1], DICT_FLAG_FOLD_FIX); mail_params_init(); if (chdir(var_queue_dir) < 0) msg_fatal("chdir(%s): %m", var_queue_dir); diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 5cee7ff28..1dcdf269d 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -316,7 +316,7 @@ int smtp_helo(SMTP_STATE *state) if (n == 0 && strcasecmp(word, var_myhostname) == 0) { if (state->misc_flags & SMTP_MISC_FLAG_LOOP_DETECT) msg_warn("host %s greeted me with my own hostname %s", - session->namaddr, var_myhostname); + session->namaddrport, var_myhostname); } else if (strcasecmp(word, "ESMTP") == 0) session->features |= SMTP_FEATURE_ESMTP; } @@ -507,16 +507,15 @@ int smtp_helo(SMTP_STATE *state) * Optionally log unused STARTTLS opportunities. */ if ((session->features & SMTP_FEATURE_STARTTLS) && - (var_smtp_tls_note_starttls_offer) && - (!(session->tls_enforce_tls || session->tls_use_tls))) + var_smtp_tls_note_starttls_offer && + session->tls_level <= SMTP_TLS_LEV_NONE) msg_info("Host offered STARTTLS: [%s]", session->host); /* * Decide whether or not to send STARTTLS. */ if ((session->features & SMTP_FEATURE_STARTTLS) != 0 - && smtp_tls_ctx != 0 - && (session->tls_use_tls || session->tls_enforce_tls)) { + && smtp_tls_ctx != 0 && session->tls_level >= SMTP_TLS_LEV_MAY) { /* * Prepare for disaster. @@ -556,7 +555,7 @@ int smtp_helo(SMTP_STATE *state) * although support for it was announced in the EHLO response. */ session->features &= ~SMTP_FEATURE_STARTTLS; - if (session->tls_enforce_tls) + if (session->tls_level >= SMTP_TLS_LEV_ENCRYPT) return (smtp_site_fail(state, session->host, resp, "TLS is required, but host %s refused to start TLS: %s", session->namaddr, @@ -571,7 +570,7 @@ int smtp_helo(SMTP_STATE *state) * block. When TLS is required we must never, ever, end up in * plain-text mode. */ - if (session->tls_enforce_tls) { + if (session->tls_level >= SMTP_TLS_LEV_ENCRYPT) { if (!(session->features & SMTP_FEATURE_STARTTLS)) { return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, SMTP_RESP_FAKE(&fake, "4.7.4"), @@ -646,9 +645,8 @@ static int smtp_start_tls(SMTP_STATE *state) session->tls_context = tls_client_start(smtp_tls_ctx, session->stream, var_smtp_starttls_tmout, - session->tls_enforce_peername, - session->host, - lowercase(vstring_str(serverid))); + session->tls_level >= SMTP_TLS_LEV_VERIFY, + session->host, lowercase(vstring_str(serverid))); vstring_free(serverid); if (session->tls_context == 0) return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, diff --git a/postfix/src/smtp/smtp_sasl_glue.c b/postfix/src/smtp/smtp_sasl_glue.c index 38e78ddcc..facf547e3 100644 --- a/postfix/src/smtp/smtp_sasl_glue.c +++ b/postfix/src/smtp/smtp_sasl_glue.c @@ -175,7 +175,7 @@ int smtp_sasl_passwd_lookup(SMTP_SESSION *session) && (value = mail_addr_find(smtp_sasl_passwd_map, state->request->sender, (char **) 0)) != 0) || (value = maps_find(smtp_sasl_passwd_map, session->host, 0)) != 0 - || (value = maps_find(smtp_sasl_passwd_map, session->dest, 0)) != 0) { + || (value = maps_find(smtp_sasl_passwd_map, session->dest, 0)) != 0) { session->sasl_username = mystrdup(value); passwd = split_at(session->sasl_username, ':'); session->sasl_passwd = mystrdup(passwd ? passwd : ""); @@ -211,7 +211,8 @@ void smtp_sasl_initialize(void) * shared locks for reading, just in case someone updates the table. */ smtp_sasl_passwd_map = maps_create("smtp_sasl_passwd", - var_smtp_sasl_passwd, DICT_FLAG_LOCK); + var_smtp_sasl_passwd, + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); if ((smtp_sasl_impl = xsasl_client_init(var_smtp_sasl_type, var_smtp_sasl_path)) == 0) msg_fatal("SASL library initialization"); diff --git a/postfix/src/smtp/smtp_session.c b/postfix/src/smtp/smtp_session.c index ccdb8fdef..080767599 100644 --- a/postfix/src/smtp/smtp_session.c +++ b/postfix/src/smtp/smtp_session.c @@ -127,16 +127,6 @@ #ifdef USE_TLS - /* - * Per-site policies can override main.cf settings. - */ -typedef struct { - int dont_use; /* don't use TLS */ - int use; /* useless, see above */ - int enforce; /* must always use TLS */ - int enforce_peername; /* must verify certificate name */ -} SMTP_TLS_SITE_POLICY; - static MAPS *tls_per_site; /* lookup table(s) */ /* smtp_tls_list_init - initialize per-site policy lists */ @@ -144,44 +134,120 @@ static MAPS *tls_per_site; /* lookup table(s) */ void smtp_tls_list_init(void) { tls_per_site = maps_create(VAR_SMTP_TLS_PER_SITE, var_smtp_tls_per_site, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); } -/* smtp_tls_site_policy - look up per-site TLS policy */ +/* smtp_tls_policy_print - printpolicy level */ -static void smtp_tls_site_policy(SMTP_TLS_SITE_POLICY *policy, - const char *site_name, - const char *site_class) +static void smtp_tls_policy_print(const char *name, int level) +{ + msg_info("%s TLS level: %s", name, + level == SMTP_TLS_LEV_VERIFY ? "verify" : + level == SMTP_TLS_LEV_ENCRYPT ? "encrypt" : + level == SMTP_TLS_LEV_MAY ? "may" : + level == SMTP_TLS_LEV_NONE ? "none" : + "unknown"); +} + +/* smtp_tls_policy_lookup - look up per-site TLS security level */ + +static void smtp_tls_policy_lookup(int *site_level, const char *site_name, + const char *site_class) { const char *lookup; - char *lookup_key; /* - * Initialize the default policy. + * Look up a non-default policy. In case of multiple lookup results, the + * precedence order is a permutation of the TLS enforcement level order: + * VERIFY, ENCRYPT, NONE, MAY, NOTFOUND. I.e. we override MAY with a more + * specific policy including NONE, otherwise we choose the stronger + * enforcement level. */ - policy->dont_use = 0; - policy->use = 0; - policy->enforce = 0; - policy->enforce_peername = 0; - - /* - * Look up a non-default policy. - */ - lookup_key = lowercase(mystrdup(site_name)); - if ((lookup = maps_find(tls_per_site, lookup_key, 0)) != 0) { - if (!strcasecmp(lookup, "NONE")) - policy->dont_use = 1; - else if (!strcasecmp(lookup, "MAY")) - policy->use = 1; - else if (!strcasecmp(lookup, "MUST")) - policy->enforce = policy->enforce_peername = 1; - else if (!strcasecmp(lookup, "MUST_NOPEERMATCH")) - policy->enforce = 1; - else + if ((lookup = maps_find(tls_per_site, site_name, 0)) != 0) { + if (!strcasecmp(lookup, "NONE")) { + /* NONE overrides MAY or NOTFOUND. */ + if (*site_level <= SMTP_TLS_LEV_MAY) + *site_level = SMTP_TLS_LEV_NONE; + } else if (!strcasecmp(lookup, "MAY")) { + /* MAY overrides NOTFOUND but not NONE. */ + if (*site_level < SMTP_TLS_LEV_NONE) + *site_level = SMTP_TLS_LEV_MAY; + } else if (!strcasecmp(lookup, "MUST_NOPEERMATCH")) { + if (*site_level < SMTP_TLS_LEV_ENCRYPT) + *site_level = SMTP_TLS_LEV_ENCRYPT; + } else if (!strcasecmp(lookup, "MUST")) { + if (*site_level < SMTP_TLS_LEV_VERIFY) + *site_level = SMTP_TLS_LEV_VERIFY; + } else { msg_warn("Table %s: ignoring unknown TLS policy '%s' for %s %s", var_smtp_tls_per_site, lookup, site_class, site_name); + } } - myfree(lookup_key); +} + +/* smtp_tls_level_init - configure session TLS enforcement level */ + +static int smtp_tls_level_init(const char *dest, const char *host) +{ + int global_level; + int site_level; + int tls_level; + + /* + * Compute the global TLS policy. This is the default policy level when + * no per-site policy exists. It also is used to override a wild-card + * per-site policy. + */ + if (var_smtp_enforce_tls) + global_level = var_smtp_tls_enforce_peername ? + SMTP_TLS_LEV_VERIFY : SMTP_TLS_LEV_ENCRYPT; + else + global_level = var_smtp_use_tls ? + SMTP_TLS_LEV_MAY : SMTP_TLS_LEV_NONE; + if (msg_verbose) + smtp_tls_policy_print("global", global_level); + + /* + * Compute the per-site TLS enforcement level. For compatibility with the + * original TLS patch, this algorithm is gives equal precedence to host + * and next-hop policies. + */ + site_level = SMTP_TLS_LEV_NOTFOUND; + + if (tls_per_site) { + smtp_tls_policy_lookup(&site_level, dest, "next-hop destination"); + if (strcasecmp(dest, host) != 0) + smtp_tls_policy_lookup(&site_level, host, "server hostname"); + if (msg_verbose) + smtp_tls_policy_print("site", site_level); + } + + /* + * Override a wild-card per-site policy with a more specific global + * policy. + * + * With the original TLS patch, 1) a per-site ENCRYPT could not override a + * global VERIFY, and 2) a combined per-site (NONE+MAY) policy produced + * inconsistent results: it changed a global VERIFY into NONE, while + * producing MAY with all weaker global policy settings. + * + * With the current implementation, a combined per-site (NONE+MAY) + * consistently overrides global policy with NONE, and global policy can + * override only a per-site MAY wildcard. That is, specific policies + * consistently override wildcard policies, and (non-wildcard) per-site + * policies consistently override global policies. + */ + if (site_level == SMTP_TLS_LEV_NOTFOUND + || (site_level == SMTP_TLS_LEV_MAY + && global_level > SMTP_TLS_LEV_MAY)) + tls_level = global_level; + else + tls_level = site_level; + + if (msg_verbose && tls_per_site) + smtp_tls_policy_print("effective", tls_level); + + return (tls_level); } #endif @@ -195,12 +261,6 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest, { SMTP_SESSION *session; -#ifdef USE_TLS - SMTP_TLS_SITE_POLICY host_policy; - SMTP_TLS_SITE_POLICY rcpt_policy; - -#endif - session = (SMTP_SESSION *) mymalloc(sizeof(*session)); session->stream = stream; session->dest = mystrdup(dest); @@ -239,44 +299,14 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest, smtp_sasl_connect(session); #endif -#ifdef USE_TLS - session->tls_use_tls = session->tls_enforce_tls = 0; - session->tls_enforce_peername = 0; - session->tls_context = 0; - /* - * Override the main.cf TLS policy with an optional per-site policy. + * Need to pass the session as a parameter when the new-style per-nexthop + * policies can specify not only security level thresholds, but also how + * security levels are defined. */ - if (smtp_tls_ctx != 0) { - smtp_tls_site_policy(&host_policy, host, "receiving host"); - smtp_tls_site_policy(&rcpt_policy, dest, "recipient domain"); - - /* - * Set up TLS enforcement for this session. - */ - if ((var_smtp_enforce_tls && !host_policy.dont_use && !rcpt_policy.dont_use) - || host_policy.enforce || rcpt_policy.enforce) - session->tls_enforce_tls = session->tls_use_tls = 1; - - /* - * Set up peername checking for this session. - * - * We want to make sure that a MUST* entry in the tls_per_site table - * always has precedence. MUST always must lead to a peername check, - * MUST_NOPEERMATCH must always disable it. Only when no explicit - * setting has been found, the default will be used. There is the - * case left, that both "host" and "recipient" settings conflict. In - * this case, the "host" setting wins. - */ - if (host_policy.enforce && host_policy.enforce_peername) - session->tls_enforce_peername = 1; - else if (rcpt_policy.enforce && rcpt_policy.enforce_peername) - session->tls_enforce_peername = 1; - else if (var_smtp_enforce_tls && var_smtp_tls_enforce_peername) - session->tls_enforce_peername = 1; - else if ((var_smtp_use_tls && !host_policy.dont_use && !rcpt_policy.dont_use) || host_policy.use || rcpt_policy.use) - session->tls_use_tls = 1; - } +#ifdef USE_TLS + session->tls_context = 0; + session->tls_level = smtp_tls_level_init(dest, host); #endif session->state = 0; debug_peer_check(host, addr); diff --git a/postfix/src/smtp/tls_policy.in b/postfix/src/smtp/tls_policy.in new file mode 100644 index 000000000..95c295bbe --- /dev/null +++ b/postfix/src/smtp/tls_policy.in @@ -0,0 +1,64 @@ +- - - +- - may +- - must_nopeermatch +- - must +- none - +- none may +- none must_nopeermatch +- none must +- may - +- may may +- may must_nopeermatch +- may must +- must_nopeermatch - +- must_nopeermatch may +- must_nopeermatch must_nopeermatch +- must_nopeermatch must +- must - +- must may +- must must_nopeermatch +- must must + +none none - +none none may +none none must_nopeermatch +none none must +none may - +none may may +none may must_nopeermatch +none may must +none must_nopeermatch - +none must_nopeermatch may +none must_nopeermatch must_nopeermatch +none must_nopeermatch must +none must - +none must may +none must must_nopeermatch +none must must + +may may - +may may may +may may must_nopeermatch +may may must +may must_nopeermatch - +may must_nopeermatch may +may must_nopeermatch must_nopeermatch +may must_nopeermatch must +may must - +may must may +may must must_nopeermatch +may must must + +must_nopeermatch must_nopeermatch - +must_nopeermatch must_nopeermatch may +must_nopeermatch must_nopeermatch must_nopeermatch +must_nopeermatch must_nopeermatch must +must_nopeermatch must - +must_nopeermatch must may +must_nopeermatch must must_nopeermatch +must_nopeermatch must must + +must must - +must must may +must must must_nopeermatch +must must must diff --git a/postfix/src/smtp/tls_policy.ref b/postfix/src/smtp/tls_policy.ref new file mode 100644 index 000000000..5b9f18799 --- /dev/null +++ b/postfix/src/smtp/tls_policy.ref @@ -0,0 +1,65 @@ +host dest global result +- - - none +- - may may +- - must_nopeermatch must_nopeermatch +- - must must +- none - none +- none may none +- none must_nopeermatch none +- none must none +- may - may +- may may may +- may must_nopeermatch must_nopeermatch +- may must must +- must_nopeermatch - must_nopeermatch +- must_nopeermatch may must_nopeermatch +- must_nopeermatch must_nopeermatch must_nopeermatch +- must_nopeermatch must must_nopeermatch +- must - must +- must may must +- must must_nopeermatch must +- must must must + +none none - none +none none may none +none none must_nopeermatch none +none none must none +none may - none +none may may none +none may must_nopeermatch none +none may must none +none must_nopeermatch - must_nopeermatch +none must_nopeermatch may must_nopeermatch +none must_nopeermatch must_nopeermatch must_nopeermatch +none must_nopeermatch must must_nopeermatch +none must - must +none must may must +none must must_nopeermatch must +none must must must + +may may - may +may may may may +may may must_nopeermatch must_nopeermatch +may may must must +may must_nopeermatch - must_nopeermatch +may must_nopeermatch may must_nopeermatch +may must_nopeermatch must_nopeermatch must_nopeermatch +may must_nopeermatch must must_nopeermatch +may must - must +may must may must +may must must_nopeermatch must +may must must must + +must_nopeermatch must_nopeermatch - must_nopeermatch +must_nopeermatch must_nopeermatch may must_nopeermatch +must_nopeermatch must_nopeermatch must_nopeermatch must_nopeermatch +must_nopeermatch must_nopeermatch must must_nopeermatch +must_nopeermatch must - must +must_nopeermatch must may must +must_nopeermatch must must_nopeermatch must +must_nopeermatch must must must + +must must - must +must must may must +must must must_nopeermatch must +must must must must diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 2776c4c91..39cac5bd0 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -4,7 +4,7 @@ SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \ smtpd_xforward.c smtpd_dsn_fix.c OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \ smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \ - smtpd_xforward.o smtpd_dsn_fix.c + smtpd_xforward.o smtpd_dsn_fix.o HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \ smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h TESTSRC = smtpd_token_test.c @@ -62,7 +62,7 @@ clean: tidy: clean tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_exp_test \ - smtpd_token_test smtpd_check_test4 smtpd_check_dsn + smtpd_token_test smtpd_check_test4 smtpd_check_dsn_test smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref smtpd_check_access ../postmap/postmap hash:smtpd_check_access @@ -260,7 +260,6 @@ smtpd_check.o: ../../include/valid_hostname.h smtpd_check.o: ../../include/valid_mailhost_addr.h smtpd_check.o: ../../include/vbuf.h smtpd_check.o: ../../include/verify_clnt.h -smtpd_check.o: ../../include/virtual8_maps.h smtpd_check.o: ../../include/vstream.h smtpd_check.o: ../../include/vstring.h smtpd_check.o: smtpd.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 664f3ddd8..a09cf0c94 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1208,13 +1208,13 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) } if ((discard_mask & EHLO_MASK_VRFY) == 0) if (var_disable_vrfy_cmd == 0) - ENQUEUE_FIX_REPLY(state, reply_buf, "VRFY"); + ENQUEUE_FIX_REPLY(state, reply_buf, SMTPD_CMD_VRFY); if ((discard_mask & EHLO_MASK_ETRN) == 0) - ENQUEUE_FIX_REPLY(state, reply_buf, "ETRN"); + ENQUEUE_FIX_REPLY(state, reply_buf, SMTPD_CMD_ETRN); #ifdef USE_TLS if ((discard_mask & EHLO_MASK_STARTTLS) == 0) if ((state->tls_use_tls || state->tls_enforce_tls) && (!state->tls_context)) - ENQUEUE_FIX_REPLY(state, reply_buf, "STARTTLS"); + ENQUEUE_FIX_REPLY(state, reply_buf, SMTPD_CMD_STARTTLS); #endif #ifdef USE_SASL_AUTH if ((discard_mask & EHLO_MASK_AUTH) == 0) { @@ -1303,7 +1303,7 @@ static void mail_open_stream(SMTPD_STATE *state) var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); @@ -1772,7 +1772,7 @@ static void mail_reset(SMTPD_STATE *state) * waiting for a reply, it just increases latency. */ if (state->proxy) { - (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT"); + (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, SMTPD_CMD_QUIT); smtpd_proxy_close(state); } if (state->xforward.flags) @@ -3223,24 +3223,24 @@ typedef struct SMTPD_CMD { #define SMTPD_CMD_FLAG_PRE_TLS (1<<1) /* allow before STARTTLS */ static SMTPD_CMD smtpd_cmd_table[] = { - "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS, - "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS, + SMTPD_CMD_HELO, helo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS, + SMTPD_CMD_EHLO, ehlo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS, #ifdef USE_TLS - "STARTTLS", starttls_cmd, SMTPD_CMD_FLAG_PRE_TLS, + SMTPD_CMD_STARTTLS, starttls_cmd, SMTPD_CMD_FLAG_PRE_TLS, #endif #ifdef USE_SASL_AUTH - "AUTH", smtpd_sasl_auth_cmd, 0, + SMTPD_CMD_AUTH, smtpd_sasl_auth_cmd, 0, #endif - "MAIL", mail_cmd, 0, - "RCPT", rcpt_cmd, 0, - "DATA", data_cmd, 0, - "RSET", rset_cmd, SMTPD_CMD_FLAG_LIMIT, - "NOOP", noop_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS, - "VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT, - "ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT, - "QUIT", quit_cmd, SMTPD_CMD_FLAG_PRE_TLS, - "XCLIENT", xclient_cmd, SMTPD_CMD_FLAG_LIMIT, - "XFORWARD", xforward_cmd, SMTPD_CMD_FLAG_LIMIT, + SMTPD_CMD_MAIL, mail_cmd, 0, + SMTPD_CMD_RCPT, rcpt_cmd, 0, + SMTPD_CMD_DATA, data_cmd, 0, + SMTPD_CMD_RSET, rset_cmd, SMTPD_CMD_FLAG_LIMIT, + SMTPD_CMD_NOOP, noop_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS, + SMTPD_CMD_VRFY, vrfy_cmd, SMTPD_CMD_FLAG_LIMIT, + SMTPD_CMD_ETRN, etrn_cmd, SMTPD_CMD_FLAG_LIMIT, + SMTPD_CMD_QUIT, quit_cmd, SMTPD_CMD_FLAG_PRE_TLS, + SMTPD_CMD_XCLIENT, xclient_cmd, SMTPD_CMD_FLAG_LIMIT, + SMTPD_CMD_XFORWARD, xforward_cmd, SMTPD_CMD_FLAG_LIMIT, 0, }; diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index f1d9af340..ebde037d0 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -186,6 +186,26 @@ extern void smtpd_state_reset(SMTPD_STATE *); #define SMTPD_AFTER_CONNECT "CONNECT" #define SMTPD_AFTER_DOT "END-OF-MESSAGE" + /* + * Other stages. These are sometimes used to change the way information is + * logged or what information will be available for access control. + */ +#define SMTPD_CMD_HELO "HELO" +#define SMTPD_CMD_EHLO "EHLO" +#define SMTPD_CMD_STARTTLS "STARTTLS" +#define SMTPD_CMD_AUTH "AUTH" +#define SMTPD_CMD_MAIL "MAIL" +#define SMTPD_CMD_RCPT "RCPT" +#define SMTPD_CMD_DATA "DATA" +#define SMTPD_CMD_EOD SMTPD_AFTER_DOT /* XXX Was: END-OF-DATA */ +#define SMTPD_CMD_RSET "RSET" +#define SMTPD_CMD_NOOP "NOOP" +#define SMTPD_CMD_VRFY "VRFY" +#define SMTPD_CMD_ETRN "ETRN" +#define SMTPD_CMD_QUIT "QUIT" +#define SMTPD_CMD_XCLIENT "XCLIENT" +#define SMTPD_CMD_XFORWARD "XFORWARD" + /* * Representation of unknown client information within smtpd processes. This * is not the representation that Postfix uses in queue files, in queue diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 9cf948c3f..2caa81af4 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -224,7 +224,6 @@ #include #include #include -#include #include #include #include @@ -510,7 +509,8 @@ static ARGV *smtpd_check_parse(int flags, const char *checks) policy_client_register(name); else if ((flags & SMTPD_CHECK_PARSE_MAPS) && strchr(name, ':') && dict_handle(name) == 0) { - dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK)); + dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX)); } last = name; } @@ -605,25 +605,25 @@ void smtpd_check_init(void) var_perm_mx_networks); #ifdef USE_TLS relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_smtpd_relay_ccerts, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); #endif /* * Pre-parse and pre-open the recipient maps. */ local_rcpt_maps = maps_create(VAR_LOCAL_RCPT_MAPS, var_local_rcpt_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); rcpt_canon_maps = maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); canonical_maps = maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); virt_alias_maps = maps_create(VAR_VIRT_ALIAS_MAPS, var_virt_alias_maps, - DICT_FLAG_LOCK); - virt_mailbox_maps = virtual8_maps_create(VAR_VIRT_MAILBOX_MAPS, - var_virt_mailbox_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); + virt_mailbox_maps = maps_create(VAR_VIRT_MAILBOX_MAPS, + var_virt_mailbox_maps, + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); relay_rcpt_maps = maps_create(VAR_RELAY_RCPT_MAPS, var_relay_rcpt_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); #ifdef TEST virt_alias_doms = string_list_init(MATCH_FLAG_NONE, var_virt_alias_doms); @@ -636,14 +636,14 @@ void smtpd_check_init(void) * Templates for RBL rejection replies. */ rbl_reply_maps = maps_create(VAR_RBL_REPLY_MAPS, var_rbl_reply_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); /* * Sender to login name mapping. */ smtpd_sender_login_maps = maps_create(VAR_SMTPD_SND_AUTH_MAPS, var_smtpd_snd_auth_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); /* * error_text is used for returning error responses. @@ -1210,7 +1210,6 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient); #ifdef USE_TLS static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) { - char *low_name; const char *found; if (!state->tls_context) @@ -1223,9 +1222,8 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) } if (state->tls_context->peer_verified && state->tls_context->peer_fingerprint) { - low_name = lowercase(mystrdup(state->tls_context->peer_fingerprint)); - found = maps_find(relay_ccerts, low_name, DICT_FLAG_FIXED); - myfree(low_name); + found = maps_find(relay_ccerts, state->tls_context->peer_fingerprint, + DICT_FLAG_NONE); if (found) { if (msg_verbose) msg_info("Relaying allowed for certified client: %s", found); @@ -1369,7 +1367,7 @@ static int reject_unauth_pipelining(SMTPD_STATE *state, && (vstream_peek(state->client) > 0 || peekfd(vstream_fileno(state->client)) > 0) && (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0 - || strcasecmp(state->where, "DATA") == 0)) { + || strcasecmp(state->where, SMTPD_CMD_DATA) == 0)) { return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL, 503, "5.5.0", "<%s>: %s rejected: Improper use of SMTP command pipelining", @@ -1794,7 +1792,7 @@ static int reject_unverified_address(SMTPD_STATE *state, const char *addr, msg_warn("%s service failure", var_verify_service); DEFER_IF_PERMIT2(state, MAIL_ERROR_POLICY, 450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? - "4.1.0" : "4.1.1", + SND_DSN : "4.1.1", "<%s>: %s rejected: address verification problem", reply_name, reply_class); rqst_status = SMTPD_CHECK_DUNNO; @@ -1808,7 +1806,7 @@ static int reject_unverified_address(SMTPD_STATE *state, const char *addr, case DEL_RCPT_STAT_DEFER: DEFER_IF_PERMIT3(state, MAIL_ERROR_POLICY, 450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? - "4.1.0" : "4.1.1", + SND_DSN : "4.1.1", "<%s>: %s rejected: unverified address: %.250s", reply_name, reply_class, STR(why)); rqst_status = SMTPD_CHECK_DUNNO; @@ -1824,7 +1822,7 @@ static int reject_unverified_address(SMTPD_STATE *state, const char *addr, smtpd_check_reject(state, MAIL_ERROR_POLICY, unv_addr_code, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? - "4.1.0" : "4.1.1", + SND_DSN : "4.1.1", "<%s>: %s rejected: undeliverable address: %s", reply_name, reply_class, STR(why)); break; @@ -1858,7 +1856,7 @@ static int can_delegate_action(SMTPD_STATE *state, const char *table, /* * ETRN does not receive mail so we can't store queue file records. */ - if (strcmp(state->where, "ETRN") == 0) { + if (strcmp(state->where, SMTPD_CMD_ETRN) == 0) { msg_warn("access table %s: action %s is unavailable in %s", table, action, VAR_ETRN_CHECKS); return (0); @@ -2241,11 +2239,11 @@ static int check_access(SMTPD_STATE *state, const char *table, const char *name, const char *reply_class, const char *def_acl) { char *myname = "check_access"; - char *low_name = lowercase(mystrdup(name)); const char *value; DICT *dict; -#define CHK_ACCESS_RETURN(x,y) { *found = y; myfree(low_name); return(x); } +#define CHK_ACCESS_RETURN(x,y) \ + { *found = y; return(x); } #define FULL 0 #define PARTIAL DICT_FLAG_FIXED #define FOUND 1 @@ -2257,7 +2255,7 @@ static int check_access(SMTPD_STATE *state, const char *table, const char *name, if ((dict = dict_handle(table)) == 0) msg_panic("%s: dictionary not found: %s", myname, table); if (flags == 0 || (flags & dict->flags) != 0) { - if ((value = dict_get(dict, low_name)) != 0) + if ((value = dict_get(dict, name)) != 0) CHK_ACCESS_RETURN(check_table_result(state, table, value, name, reply_name, reply_class, def_acl), FOUND); @@ -2276,9 +2274,8 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, const char *def_acl) { char *myname = "check_domain_access"; - char *low_domain = lowercase(mystrdup(domain)); - char *name; - char *next; + const char *name; + const char *next; const char *value; DICT *dict; int maybe_numerical = 1; @@ -2293,11 +2290,11 @@ static int check_domain_access(SMTPD_STATE *state, const char *table, * key, because Berkeley DB cannot deal with it. [Victor Duchovni, Morgan * Stanley]. */ -#define CHK_DOMAIN_RETURN(x,y) { *found = y; myfree(low_domain); return(x); } +#define CHK_DOMAIN_RETURN(x,y) { *found = y; return(x); } if ((dict = dict_handle(table)) == 0) msg_panic("%s: dictionary not found: %s", myname, table); - for (name = low_domain; *name != 0; name = next) { + for (name = domain; *name != 0; name = next) { if (flags == 0 || (flags & dict->flags) != 0) { if ((value = dict_get(dict, name)) != 0) CHK_DOMAIN_RETURN(check_table_result(state, table, value, @@ -2965,7 +2962,6 @@ static int rbl_reject_reply(SMTPD_STATE *state, SMTPD_RBL_STATE *rbl, const char *myname = "rbl_reject_reply"; VSTRING *why = 0; const char *template = 0; - char *low_name; SMTPD_RBL_EXPAND_CONTEXT rbl_exp; int result; DSN_SPLIT dp; @@ -2975,9 +2971,7 @@ static int rbl_reject_reply(SMTPD_STATE *state, SMTPD_RBL_STATE *rbl, * Use the server-specific reply template or use the default one. */ if (*var_rbl_reply_maps) { - low_name = lowercase(mystrdup(rbl_domain)); - template = maps_find(rbl_reply_maps, low_name, 0); - myfree(low_name); + template = maps_find(rbl_reply_maps, rbl_domain, DICT_FLAG_NONE); } why = vstring_alloc(100); rbl_exp.state = state; @@ -3273,6 +3267,10 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, state->sender ? state->sender : "", ATTR_TYPE_STR, MAIL_ATTR_RECIP, state->recipient ? state->recipient : "", + ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, + ((strcasecmp(state->where, SMTPD_CMD_DATA) == 0) || + (strcasecmp(state->where, SMTPD_AFTER_DOT) == 0)) ? + state->rcpt_count : 0, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->queue_id ? state->queue_id : "", ATTR_TYPE_STR, MAIL_ATTR_INSTANCE, @@ -3306,8 +3304,8 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, IF_ENCRYPTED(state->tls_context->protocol, ""), ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_CIPHER, IF_ENCRYPTED(state->tls_context->cipher_name, ""), - ATTR_TYPE_NUM, MAIL_ATTR_CRYPTO_KEYSIZE, - IF_ENCRYPTED(state->tls_context->cipher_usebits, 0), + ATTR_TYPE_INT, MAIL_ATTR_CRYPTO_KEYSIZE, + IF_ENCRYPTED(state->tls_context->cipher_usebits, 0), #endif ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes. */ @@ -3751,7 +3749,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, status = check_recipient_rcpt_maps(state, state->recipient); } else if (strcasecmp(name, REJECT_MUL_RCPT_BOUNCE) == 0) { if (state->sender && *state->sender == 0 && state->rcpt_count - > (strcmp(state->where, "DATA") ? 0 : 1)) + > (strcmp(state->where, SMTPD_CMD_DATA) ? 0 : 1)) status = smtpd_check_reject(state, MAIL_ERROR_POLICY, var_mul_rcpt_code, "5.5.3", "<%s>: %s rejected: Multi-recipient bounce", @@ -4303,9 +4301,9 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient, /* * Search the recipient lookup tables of the respective address class. * - * XXX Use the less expensive maps_find() (case is already folded) instead - * of the baroque mail_addr_find(). But then we have to strip the domain - * and deal with address extensions ourselves. + * XXX Use the less expensive maps_find() (built-in case folding) instead of + * the baroque mail_addr_find(). But then we have to strip the domain and + * deal with address extensions ourselves. * * XXX But that would break sites that use the virtual delivery agent for * local delivery, because the virtual delivery agent requires @@ -4481,7 +4479,7 @@ char *smtpd_check_data(SMTPD_STATE *state) status = setjmp(smtpd_check_buf); if (status == 0 && data_restrctions->argc) status = generic_checks(state, data_restrctions, - "DATA", SMTPD_NAME_DATA, NO_DEF_ACL); + SMTPD_CMD_DATA, SMTPD_NAME_DATA, NO_DEF_ACL); /* * Force permission into deferral when some earlier temporary error may @@ -4532,7 +4530,7 @@ char *smtpd_check_eod(SMTPD_STATE *state) status = setjmp(smtpd_check_buf); if (status == 0 && eod_restrictions->argc) status = generic_checks(state, eod_restrictions, - "END-OF-DATA", SMTPD_NAME_EOD, NO_DEF_ACL); + SMTPD_CMD_EOD, SMTPD_NAME_EOD, NO_DEF_ACL); /* * Force permission into deferral when some earlier temporary error may @@ -4728,6 +4726,8 @@ int var_smtpd_policy_idle; int var_smtpd_policy_ttl; int var_smtpd_rej_unl_from; int var_smtpd_rej_unl_rcpt; +int var_plaintext_code; +bool var_smtpd_peername_lookup; static INT_TABLE int_table[] = { "msg_verbose", 0, &msg_verbose, @@ -4754,6 +4754,8 @@ static INT_TABLE int_table[] = { VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from, VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt, + VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, + VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup, 0, }; @@ -4905,7 +4907,8 @@ VSTRING *rewrite_clnt_internal(const char *context, const char *addr, /* resolve_clnt_query - stub */ -void resolve_clnt(const char *class, const char *addr, RESOLVE_REPLY *reply) +void resolve_clnt(const char *class, const char *unused_sender, const char *addr, + RESOLVE_REPLY *reply) { const char *domain; @@ -5020,6 +5023,10 @@ int main(int argc, char **argv) state.name_status = state.reverse_name_status = atoi(args->argv[3]); + else if (strcmp(state.name, "unknown") == 0) + state.name_status = + state.reverse_name_status = + SMTPD_PEER_CODE_TEMP; else state.name_status = state.reverse_name_status = @@ -5046,7 +5053,8 @@ int main(int argc, char **argv) if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_MAPS) == 0) { UPDATE_STRING(var_virt_alias_maps, args->argv[1]); UPDATE_MAPS(virt_alias_maps, VAR_VIRT_ALIAS_MAPS, - var_virt_alias_maps, DICT_FLAG_LOCK); + var_virt_alias_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); resp = 0; break; } @@ -5059,7 +5067,8 @@ int main(int argc, char **argv) if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_MAPS) == 0) { UPDATE_STRING(var_virt_mailbox_maps, args->argv[1]); UPDATE_MAPS(virt_mailbox_maps, VAR_VIRT_MAILBOX_MAPS, - var_virt_mailbox_maps, DICT_FLAG_LOCK); + var_virt_mailbox_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); resp = 0; break; } @@ -5072,28 +5081,32 @@ int main(int argc, char **argv) if (strcasecmp(args->argv[0], VAR_LOCAL_RCPT_MAPS) == 0) { UPDATE_STRING(var_local_rcpt_maps, args->argv[1]); UPDATE_MAPS(local_rcpt_maps, VAR_LOCAL_RCPT_MAPS, - var_local_rcpt_maps, DICT_FLAG_LOCK); + var_local_rcpt_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); resp = 0; break; } if (strcasecmp(args->argv[0], VAR_RELAY_RCPT_MAPS) == 0) { UPDATE_STRING(var_relay_rcpt_maps, args->argv[1]); UPDATE_MAPS(relay_rcpt_maps, VAR_RELAY_RCPT_MAPS, - var_relay_rcpt_maps, DICT_FLAG_LOCK); + var_relay_rcpt_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); resp = 0; break; } if (strcasecmp(args->argv[0], VAR_CANONICAL_MAPS) == 0) { UPDATE_STRING(var_canonical_maps, args->argv[1]); UPDATE_MAPS(canonical_maps, VAR_CANONICAL_MAPS, - var_canonical_maps, DICT_FLAG_LOCK); + var_canonical_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); resp = 0; break; } if (strcasecmp(args->argv[0], VAR_RBL_REPLY_MAPS) == 0) { UPDATE_STRING(var_rbl_reply_maps, args->argv[1]); UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS, - var_rbl_reply_maps, DICT_FLAG_LOCK); + var_rbl_reply_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); resp = 0; break; } diff --git a/postfix/src/smtpd/smtpd_check.ref b/postfix/src/smtpd/smtpd_check.ref index 073468b23..7dcd49728 100644 --- a/postfix/src/smtpd/smtpd_check.ref +++ b/postfix/src/smtpd/smtpd_check.ref @@ -49,11 +49,11 @@ OK >>> client foo 123.123.123.123 OK >>> helo foo. -./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.1.0 : Helo command rejected: Host not found; proto=SMTP helo= -450 4.1.0 : Helo command rejected: Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.7.1 : Helo command rejected: Host not found; proto=SMTP helo= +450 4.7.1 : Helo command rejected: Host not found >>> helo foo -./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.1.0 : Helo command rejected: Host not found; proto=SMTP helo= -450 4.1.0 : Helo command rejected: Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.7.1 : Helo command rejected: Host not found; proto=SMTP helo= +450 4.7.1 : Helo command rejected: Host not found >>> helo spike.porcupine.org ./smtpd_check: : reject: HELO from foo[123.123.123.123]: 554 5.7.1 : Helo command rejected: name server spike.porcupine.org; proto=SMTP helo= 554 5.7.1 : Helo command rejected: name server spike.porcupine.org @@ -67,8 +67,8 @@ OK >>> helo_restrictions reject_invalid_hostname,reject_unknown_hostname OK >>> helo 123.123.123.123 -./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.1.0 <123.123.123.123>: Helo command rejected: Host not found; proto=SMTP helo=<123.123.123.123> -450 4.1.0 <123.123.123.123>: Helo command rejected: Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.7.1 <123.123.123.123>: Helo command rejected: Host not found; proto=SMTP helo=<123.123.123.123> +450 4.7.1 <123.123.123.123>: Helo command rejected: Host not found >>> helo [123.123.123.123] OK >>> helo [::] diff --git a/postfix/src/smtpd/smtpd_check.ref2 b/postfix/src/smtpd/smtpd_check.ref2 index df0c2174a..0553750ac 100644 --- a/postfix/src/smtpd/smtpd_check.ref2 +++ b/postfix/src/smtpd/smtpd_check.ref2 @@ -49,11 +49,11 @@ OK >>> client foo 123.123.123.123 OK >>> helo foo. -./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.1.0 : Helo command rejected: Host not found; proto=SMTP helo= -450 4.1.0 : Helo command rejected: Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.7.1 : Helo command rejected: Host not found; proto=SMTP helo= +450 4.7.1 : Helo command rejected: Host not found >>> helo foo -./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.1.0 : Helo command rejected: Host not found; proto=SMTP helo= -450 4.1.0 : Helo command rejected: Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 4.7.1 : Helo command rejected: Host not found; proto=SMTP helo= +450 4.7.1 : Helo command rejected: Host not found >>> helo spike.porcupine.org ./smtpd_check: : reject: HELO from foo[123.123.123.123]: 554 5.7.1 : Helo command rejected: name server spike.porcupine.org; proto=SMTP helo= 554 5.7.1 : Helo command rejected: name server spike.porcupine.org diff --git a/postfix/src/smtpd/smtpd_check_dsn.ref b/postfix/src/smtpd/smtpd_check_dsn.ref index 25afca7c0..87b1bb9e9 100644 --- a/postfix/src/smtpd/smtpd_check_dsn.ref +++ b/postfix/src/smtpd/smtpd_check_dsn.ref @@ -95,9 +95,9 @@ OK >>> sender_restrictions hash:./smtpd_check_access OK >>> mail user@4.1.1_dsn -./smtpd_check: mapping DSN status 4.1.1 into Sender address status 4.1.0 -./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.0 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> -554 5.1.0 : Sender address rejected: reject +./smtpd_check: mapping DSN status 4.1.1 into Sender address status 4.1.7 +./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.7 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> +554 5.1.7 : Sender address rejected: reject >>> mail user@4.1.2_dsn ./smtpd_check: mapping DSN status 4.1.2 into Sender address status 4.1.8 ./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.8 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> @@ -107,17 +107,17 @@ OK ./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.7 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> 554 5.1.7 : Sender address rejected: reject >>> mail user@4.1.4_dsn -./smtpd_check: mapping DSN status 4.1.4 into Sender address status 4.1.0 -./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.0 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> -554 5.1.0 : Sender address rejected: reject +./smtpd_check: mapping DSN status 4.1.4 into Sender address status 4.1.7 +./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.7 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> +554 5.1.7 : Sender address rejected: reject >>> mail user@4.1.5_dsn ./smtpd_check: mapping DSN status 4.1.5 into Sender address status 4.1.0 ./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.0 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> 554 5.1.0 : Sender address rejected: reject >>> mail user@4.1.6_dsn -./smtpd_check: mapping DSN status 4.1.6 into Sender address status 4.1.0 -./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.0 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> -554 5.1.0 : Sender address rejected: reject +./smtpd_check: mapping DSN status 4.1.6 into Sender address status 4.1.7 +./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.7 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> +554 5.1.7 : Sender address rejected: reject >>> mail user@4.1.7_dsn ./smtpd_check: : reject: MAIL from dummy[dummy]: 554 5.1.7 : Sender address rejected: reject; from= proto=SMTP helo=<4.4.0_dsn> 554 5.1.7 : Sender address rejected: reject diff --git a/postfix/src/smtpd/smtpd_dsn_fix.c b/postfix/src/smtpd/smtpd_dsn_fix.c index bf37f9c33..d43696728 100644 --- a/postfix/src/smtpd/smtpd_dsn_fix.c +++ b/postfix/src/smtpd/smtpd_dsn_fix.c @@ -78,12 +78,12 @@ struct dsn_map { static struct dsn_map dsn_map[] = { /* - Sender - Recipient */ - "1", "4.1.0", "4.1.1", /* 4.1.1: Bad dest mbox addr */ + "1", SND_DSN, "4.1.1", /* 4.1.1: Bad dest mbox addr */ "2", "4.1.8", "4.1.2", /* 4.1.2: Bad dest system addr */ "3", "4.1.7", "4.1.3", /* 4.1.3: Bad dest mbox addr syntax */ - "4", "4.1.0", "4.1.4", /* 4.1.4: Dest mbox addr ambiguous */ + "4", SND_DSN, "4.1.4", /* 4.1.4: Dest mbox addr ambiguous */ "5", "4.1.0", "4.1.5", /* 4.1.5: Dest mbox addr valid */ - "6", "4.1.0", "4.1.6", /* 4.1.6: Mailbox has moved */ + "6", SND_DSN, "4.1.6", /* 4.1.6: Mailbox has moved */ "7", "4.1.7", "4.1.3", /* 4.1.7: Bad sender mbox addr syntax */ "8", "4.1.8", "4.1.2", /* 4.1.8: Bad sender system addr */ 0, "4.1.0", "4.1.0", /* Default mapping */ diff --git a/postfix/src/smtpd/smtpd_dsn_fix.h b/postfix/src/smtpd/smtpd_dsn_fix.h index fa9a4450f..a3a42dff5 100644 --- a/postfix/src/smtpd/smtpd_dsn_fix.h +++ b/postfix/src/smtpd/smtpd_dsn_fix.h @@ -21,6 +21,13 @@ #define SMTPD_NAME_DATA "Data command" #define SMTPD_NAME_EOD "End-of-data" + /* + * Workaround for absence of "bad sender address" status code: use "bad + * sender address syntax" instead. If we were to use "4.1.0" then we would + * lose the critical distinction between sender and recipient problems. + */ +#define SND_DSN "4.1.7" + extern const char *smtpd_dsn_fix(const char *, const char *); /* LICENSE diff --git a/postfix/src/spawn/Makefile.in b/postfix/src/spawn/Makefile.in index f79a8f265..8295ce99c 100644 --- a/postfix/src/spawn/Makefile.in +++ b/postfix/src/spawn/Makefile.in @@ -69,4 +69,5 @@ spawn.o: ../../include/sys_defs.h spawn.o: ../../include/timed_wait.h spawn.o: ../../include/vbuf.h spawn.o: ../../include/vstream.h +spawn.o: ../../include/vstring.h spawn.o: spawn.c diff --git a/postfix/src/tls/tls_mgr.c b/postfix/src/tls/tls_mgr.c index 0e1cdf93c..c493775c0 100644 --- a/postfix/src/tls/tls_mgr.c +++ b/postfix/src/tls/tls_mgr.c @@ -164,10 +164,10 @@ int tls_mgr_seed(VSTRING *buf, int len) if (attr_clnt_request(tls_mgr, ATTR_FLAG_NONE, /* Request attributes */ ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_SEED, - ATTR_TYPE_NUM, TLS_MGR_ATTR_SIZE, len, + ATTR_TYPE_INT, TLS_MGR_ATTR_SIZE, len, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes */ - ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status, + ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status, ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED, buf, ATTR_TYPE_END) != 2) status = TLS_MGR_STAT_FAIL; @@ -194,8 +194,8 @@ int tls_mgr_policy(int *policy) ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_POLICY, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply attributes */ - ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status, - ATTR_TYPE_NUM, TLS_MGR_ATTR_POLICY, policy, + ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status, + ATTR_TYPE_INT, TLS_MGR_ATTR_POLICY, policy, ATTR_TYPE_END) != 2) status = TLS_MGR_STAT_FAIL; return (status); @@ -219,11 +219,11 @@ int tls_mgr_lookup(int cache_type, const char *cache_id, VSTRING *buf) if (attr_clnt_request(tls_mgr, ATTR_FLAG_NONE, /* Request */ ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_LOOKUP, - ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, cache_type, + ATTR_TYPE_INT, TLS_MGR_ATTR_CACHE_TYPE, cache_type, ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply */ - ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status, + ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status, ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buf, ATTR_TYPE_END) != 2) status = TLS_MGR_STAT_FAIL; @@ -249,12 +249,12 @@ int tls_mgr_update(int cache_type, const char *cache_id, if (attr_clnt_request(tls_mgr, ATTR_FLAG_NONE, /* Request */ ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_UPDATE, - ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, cache_type, + ATTR_TYPE_INT, TLS_MGR_ATTR_CACHE_TYPE, cache_type, ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id, ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, len, buf, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply */ - ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status, + ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) status = TLS_MGR_STAT_FAIL; return (status); @@ -278,11 +278,11 @@ int tls_mgr_delete(int cache_type, const char *cache_id) if (attr_clnt_request(tls_mgr, ATTR_FLAG_NONE, /* Request */ ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_DELETE, - ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, cache_type, + ATTR_TYPE_INT, TLS_MGR_ATTR_CACHE_TYPE, cache_type, ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id, ATTR_TYPE_END, ATTR_FLAG_MISSING, /* Reply */ - ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status, + ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) status = TLS_MGR_STAT_FAIL; return (status); diff --git a/postfix/src/tls/tls_verify.c b/postfix/src/tls/tls_verify.c index 91a85ed6f..042ee2984 100644 --- a/postfix/src/tls/tls_verify.c +++ b/postfix/src/tls/tls_verify.c @@ -199,9 +199,14 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx) static char *tls_text_name(X509_NAME *name, int nid, char *label, int gripe) { int len; - char *text; + int pos; + X509_NAME_ENTRY *entry; + ASN1_STRING *entry_str; + unsigned char *tmp; + char *result; - if ((len = X509_NAME_get_text_by_NID(name, nid, 0, 0)) < 0) { + if (name == 0 + || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) { if (gripe != DONT_GRIPE) { msg_warn("peer certificate has no %s", label); tls_print_errors(); @@ -209,22 +214,61 @@ static char *tls_text_name(X509_NAME *name, int nid, char *label, int gripe) return (0); } +#if 0 + /* + * If the match is required unambiguous, insist that that no + * other values be present. + */ + if (unique == UNIQUE && X509_NAME_get_index_by_NID(name, nid, pos) >= 0) { + msg_warn("multiple %ss in peer certificate", label); + return (0); + } +#endif + + if ((entry = X509_NAME_get_entry(name, pos)) == 0) { + /* This should not happen */ + msg_warn("error reading peer certificate %s entry", label); + tls_print_errors(); + return (0); + } + + if ((entry_str = X509_NAME_ENTRY_get_data(entry)) == 0) { + /* This should not happen */ + msg_warn("error reading peer certificate %s data", label); + tls_print_errors(); + return (0); + } + + if ((len = ASN1_STRING_to_UTF8(&tmp, entry_str)) < 0) { + /* This should not happen */ + msg_warn("error decoding peer certificate %s data", label); + tls_print_errors(); + return (0); + } + /* * Since the peer CN is used in peer verification, take care to detect * truncation due to excessive length or internal NULs. */ if (len >= CCERT_BUFSIZ) { + OPENSSL_free(tmp); msg_warn("peer %s too long: %d", label, (int) len); return (0); } - text = mymalloc(len + 1); - X509_NAME_get_text_by_NID(name, nid, text, len + 1); - if (strlen(text) != len) { + + /* + * Standard UTF8 does not encode NUL as 0b11000000, that is + * a Java "feature". So we need to check for embedded NULs. + */ + if (strlen(tmp) != len) { msg_warn("internal NUL in peer %s", label); - myfree(text); - text = 0; + OPENSSL_free(tmp); + return (0); } - return (text); + + result = mystrdup(tmp); + OPENSSL_free(tmp); + return (result); } /* tls_peer_CN - extract peer common name from certificate */ @@ -234,7 +278,7 @@ char *tls_peer_CN(X509 *peercert) char *cn; cn = tls_text_name(X509_get_subject_name(peercert), - NID_commonName, "CN", DO_GRIPE); + NID_commonName, "subject CN", DO_GRIPE); return (cn); } diff --git a/postfix/src/tlsmgr/tlsmgr.c b/postfix/src/tlsmgr/tlsmgr.c index 565152397..e086e2c31 100644 --- a/postfix/src/tlsmgr/tlsmgr.c +++ b/postfix/src/tlsmgr/tlsmgr.c @@ -556,7 +556,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, */ if (STREQ(STR(request), TLS_MGR_REQ_LOOKUP)) { if (attr_scan(client_stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, &cache_type, + ATTR_TYPE_INT, TLS_MGR_ATTR_CACHE_TYPE, &cache_type, ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id, ATTR_TYPE_END) == 2) { if ((cache = WHICH_CACHE_INFO(cache_type)) == 0) { @@ -569,7 +569,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, } } attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, LEN(buffer), STR(buffer), ATTR_TYPE_END); @@ -580,7 +580,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, */ else if (STREQ(STR(request), TLS_MGR_REQ_UPDATE)) { if (attr_scan(client_stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, &cache_type, + ATTR_TYPE_INT, TLS_MGR_ATTR_CACHE_TYPE, &cache_type, ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id, ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buffer, ATTR_TYPE_END) == 3) { @@ -595,7 +595,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, } } attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); } @@ -604,7 +604,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, */ else if (STREQ(STR(request), TLS_MGR_REQ_DELETE)) { if (attr_scan(client_stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, &cache_type, + ATTR_TYPE_INT, TLS_MGR_ATTR_CACHE_TYPE, &cache_type, ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id, ATTR_TYPE_END) == 2) { if ((cache = WHICH_CACHE_INFO(cache_type)) == 0) { @@ -616,7 +616,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, } } attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_END); } @@ -625,7 +625,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, */ else if (STREQ(STR(request), TLS_MGR_REQ_SEED)) { if (attr_scan(client_stream, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, TLS_MGR_ATTR_SIZE, &len, + ATTR_TYPE_INT, TLS_MGR_ATTR_SIZE, &len, ATTR_TYPE_END) == 1) { VSTRING_RESET(buffer); if (len <= 0 || len > 255) { @@ -640,7 +640,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, } } attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED, LEN(buffer), STR(buffer), ATTR_TYPE_END); @@ -661,8 +661,8 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, status = TLS_MGR_STAT_OK; } attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status, - ATTR_TYPE_NUM, TLS_MGR_ATTR_POLICY, cache_types, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, status, + ATTR_TYPE_INT, TLS_MGR_ATTR_POLICY, cache_types, ATTR_TYPE_END); } @@ -690,7 +690,7 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service, */ else { attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, TLS_MGR_STAT_FAIL, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, TLS_MGR_STAT_FAIL, ATTR_TYPE_END); } vstream_fflush(client_stream); diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index f961b0111..b72619957 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -661,11 +661,11 @@ int resolve_proto(RES_CONTEXT *context, VSTREAM *stream) STR(nexthop), STR(nextrcpt), flags); attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, server_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, server_flags, ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, STR(channel), ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, STR(nexthop), ATTR_TYPE_STR, MAIL_ATTR_RECIP, STR(nextrcpt), - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_END); if (vstream_fflush(stream) != 0) { @@ -701,5 +701,5 @@ void resolve_init(void) if (*var_relocated_maps) relocated_maps = maps_create(VAR_RELOCATED_MAPS, var_relocated_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); } diff --git a/postfix/src/trivial-rewrite/rewrite.c b/postfix/src/trivial-rewrite/rewrite.c index c1a275f99..ac0ffbadf 100644 --- a/postfix/src/trivial-rewrite/rewrite.c +++ b/postfix/src/trivial-rewrite/rewrite.c @@ -259,7 +259,7 @@ int rewrite_proto(VSTREAM *stream) vstring_str(address), vstring_str(result)); attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, server_flags, + ATTR_TYPE_INT, MAIL_ATTR_FLAGS, server_flags, ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result), ATTR_TYPE_END); diff --git a/postfix/src/trivial-rewrite/transport.c b/postfix/src/trivial-rewrite/transport.c index db6bc26c9..890517746 100644 --- a/postfix/src/trivial-rewrite/transport.c +++ b/postfix/src/trivial-rewrite/transport.c @@ -97,7 +97,8 @@ TRANSPORT_INFO *transport_pre_init(const char *transport_maps_name, tp = (TRANSPORT_INFO *) mymalloc(sizeof(*tp)); tp->transport_path = maps_create(transport_maps_name, transport_maps, - DICT_FLAG_LOCK); + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX + | DICT_FLAG_NO_REGSUB); tp->wildcard_channel = tp->wildcard_nexthop = 0; tp->transport_errno = 0; return (tp); @@ -244,7 +245,6 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, const char *rcpt_domain, VSTRING *channel, VSTRING *nexthop) { - char *full_addr; char *stripped_addr; char *ratsign = 0; const char *name; @@ -261,44 +261,34 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, msg_warn("transport_lookup: null address - skipping table lookup"); return (NOTFOUND); } - full_addr = lowercase(mystrdup(addr)); - - /* - * The optimizer will replace multiple instances of this macro expansion - * by gotos to a single instance that does the same thing. - */ -#define RETURN_FREE(x) { \ - myfree(full_addr); \ - return (x); \ - } /* * Look up the full address with the FULL flag to include regexp maps in * the query. */ - if ((ratsign = strrchr(full_addr, '@')) == 0 || ratsign[1] == 0) - msg_panic("transport_lookup: bad address: \"%s\"", full_addr); + if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0) + msg_panic("transport_lookup: bad address: \"%s\"", addr); - if (find_transport_entry(tp, full_addr, rcpt_domain, FULL, channel, nexthop)) - RETURN_FREE(FOUND); + if (find_transport_entry(tp, addr, rcpt_domain, FULL, channel, nexthop)) + return (FOUND); if (dict_errno != 0) - RETURN_FREE(NOTFOUND); + return (NOTFOUND); /* * If the full address did not match, and there is an address extension, * look up the stripped address with the PARTIAL flag to avoid matching * partial lookup keys with regular expressions. */ - if ((stripped_addr = strip_addr(full_addr, DISCARD_EXTENSION, + if ((stripped_addr = strip_addr(addr, DISCARD_EXTENSION, *var_rcpt_delim)) != 0) { found = find_transport_entry(tp, stripped_addr, rcpt_domain, PARTIAL, channel, nexthop); myfree(stripped_addr); if (found) - RETURN_FREE(FOUND); + return (FOUND); if (dict_errno != 0) - RETURN_FREE(NOTFOUND); + return (NOTFOUND); } /* @@ -319,9 +309,9 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, */ for (name = ratsign + 1; *name != 0; name = next) { if (find_transport_entry(tp, name, rcpt_domain, PARTIAL, channel, nexthop)) - RETURN_FREE(FOUND); + return (FOUND); if (dict_errno != 0) - RETURN_FREE(NOTFOUND); + return (NOTFOUND); if ((next = strchr(name + 1, '.')) == 0) break; if (transport_match_parent_style == MATCH_FLAG_PARENT) @@ -335,15 +325,15 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr, transport_wildcard_init(tp); if (tp->transport_errno) { dict_errno = tp->transport_errno; - RETURN_FREE(NOTFOUND); + return (NOTFOUND); } else if (tp->wildcard_channel) { update_entry(STR(tp->wildcard_channel), STR(tp->wildcard_nexthop), rcpt_domain, channel, nexthop); - RETURN_FREE(FOUND); + return (FOUND); } /* * We really did not find it. */ - RETURN_FREE(NOTFOUND); + return (NOTFOUND); } diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index 9852dea32..cdcd6dba8 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -506,11 +506,15 @@ static void pre_jail_init(char *unused_name, char **unused_argv) if (*RES_PARAM_VALUE(resolve_regular.snd_relay_maps)) resolve_regular.snd_relay_info = maps_create(resolve_regular.snd_relay_maps_name, - RES_PARAM_VALUE(resolve_regular.snd_relay_maps), 0); + RES_PARAM_VALUE(resolve_regular.snd_relay_maps), + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX + | DICT_FLAG_NO_REGSUB); if (*RES_PARAM_VALUE(resolve_verify.snd_relay_maps)) resolve_verify.snd_relay_info = maps_create(resolve_verify.snd_relay_maps_name, - RES_PARAM_VALUE(resolve_verify.snd_relay_maps), 0); + RES_PARAM_VALUE(resolve_verify.snd_relay_maps), + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX + | DICT_FLAG_NO_REGSUB); } /* post_jail_init - initialize after entering chroot jail */ diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 8e3cb4e08..cb1b23c14 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -713,6 +713,7 @@ dict.o: mac_expand.h dict.o: mac_parse.h dict.o: msg.h dict.o: mymalloc.h +dict.o: name_mask.h dict.o: readlline.h dict.o: stringops.h dict.o: sys_defs.h @@ -727,6 +728,7 @@ dict_alloc.o: mymalloc.h dict_alloc.o: sys_defs.h dict_alloc.o: vbuf.h dict_alloc.o: vstream.h +dict_alloc.o: vstring.h dict_cdb.o: argv.h dict_cdb.o: dict.h dict_cdb.o: dict_cdb.c @@ -777,6 +779,7 @@ dict_debug.o: mymalloc.h dict_debug.o: sys_defs.h dict_debug.o: vbuf.h dict_debug.o: vstream.h +dict_debug.o: vstring.h dict_env.o: argv.h dict_env.o: dict.h dict_env.o: dict_env.c @@ -784,9 +787,11 @@ dict_env.o: dict_env.h dict_env.o: msg.h dict_env.o: mymalloc.h dict_env.o: safe.h +dict_env.o: stringops.h dict_env.o: sys_defs.h dict_env.o: vbuf.h dict_env.o: vstream.h +dict_env.o: vstring.h dict_ht.o: argv.h dict_ht.o: dict.h dict_ht.o: dict_ht.c @@ -796,6 +801,7 @@ dict_ht.o: mymalloc.h dict_ht.o: sys_defs.h dict_ht.o: vbuf.h dict_ht.o: vstream.h +dict_ht.o: vstring.h dict_ni.o: dict_ni.c dict_ni.o: sys_defs.h dict_nis.o: argv.h @@ -804,6 +810,7 @@ dict_nis.o: dict_nis.c dict_nis.o: dict_nis.h dict_nis.o: msg.h dict_nis.o: mymalloc.h +dict_nis.o: stringops.h dict_nis.o: sys_defs.h dict_nis.o: vbuf.h dict_nis.o: vstream.h @@ -896,6 +903,7 @@ dict_static.o: mymalloc.h dict_static.o: sys_defs.h dict_static.o: vbuf.h dict_static.o: vstream.h +dict_static.o: vstring.h dict_tcp.o: argv.h dict_tcp.o: connect.h dict_tcp.o: dict.h @@ -917,6 +925,7 @@ dict_unix.o: dict_unix.c dict_unix.o: dict_unix.h dict_unix.o: msg.h dict_unix.o: mymalloc.h +dict_unix.o: stringops.h dict_unix.o: sys_defs.h dict_unix.o: vbuf.h dict_unix.o: vstream.h @@ -1101,6 +1110,8 @@ inet_proto.o: myaddrinfo.h inet_proto.o: mymalloc.h inet_proto.o: name_mask.h inet_proto.o: sys_defs.h +inet_proto.o: vbuf.h +inet_proto.o: vstring.h inet_trigger.o: connect.h inet_trigger.o: events.h inet_trigger.o: inet_trigger.c diff --git a/postfix/src/util/attr.h b/postfix/src/util/attr.h index 47f757635..cdaeb79a9 100644 --- a/postfix/src/util/attr.h +++ b/postfix/src/util/attr.h @@ -25,7 +25,8 @@ * Attribute types. See attr_scan(3) for documentation. */ #define ATTR_TYPE_END 0 /* end of data */ -#define ATTR_TYPE_NUM 1 /* Unsigned integer */ +#define ATTR_TYPE_INT 1 /* Unsigned integer */ +#define ATTR_TYPE_NUM ATTR_TYPE_INT #define ATTR_TYPE_STR 2 /* Character string */ #define ATTR_TYPE_HASH 3 /* Hash table */ #define ATTR_TYPE_NV 3 /* Name-value table */ @@ -104,7 +105,7 @@ extern int attr_vscan_plain(VSTREAM *, int, va_list); * routines. */ #ifdef TEST -#define ATTR_NAME_NUM "number" +#define ATTR_NAME_INT "number" #define ATTR_NAME_STR "string" #define ATTR_NAME_LONG "long_number" #define ATTR_NAME_DATA "data" diff --git a/postfix/src/util/attr_clnt.c b/postfix/src/util/attr_clnt.c index 87aac7574..ea601b704 100644 --- a/postfix/src/util/attr_clnt.c +++ b/postfix/src/util/attr_clnt.c @@ -166,7 +166,7 @@ int attr_clnt_request(ATTR_CLNT *client, int send_flags,...) case ATTR_TYPE_DATA: SKIP_ARG2(ap, ssize_t, char *); break; - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: SKIP_ARG(ap, int); break; case ATTR_TYPE_LONG: @@ -190,7 +190,8 @@ int attr_clnt_request(ATTR_CLNT *client, int send_flags,...) if (++count >= 2 || msg_verbose || (errno && errno != EPIPE && errno != ENOENT && errno != ECONNRESET)) - msg_warn("problem talking to server %s: %m", VSTREAM_PATH(stream)); + msg_warn("problem talking to server %s: %m", + auto_clnt_name(client->auto_clnt)); if (count >= 2) return (-1); sleep(1); /* XXX make configurable */ diff --git a/postfix/src/util/attr_print0.c b/postfix/src/util/attr_print0.c index 04222e459..339388605 100644 --- a/postfix/src/util/attr_print0.c +++ b/postfix/src/util/attr_print0.c @@ -44,7 +44,7 @@ /* .IP type /* The type determines the arguments that follow. /* .RS -/* .IP "ATTR_TYPE_NUM (char *, int)" +/* .IP "ATTR_TYPE_INT (char *, int)" /* This argument is followed by an attribute name and an integer. /* .IP "ATTR_TYPE_LONG (char *, long)" /* This argument is followed by an attribute name and a long integer. @@ -130,7 +130,7 @@ int attr_vprint0(VSTREAM *fp, int flags, va_list ap) */ while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { switch (attr_type) { - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: attr_name = va_arg(ap, char *); vstream_fwrite(fp, attr_name, strlen(attr_name) + 1); int_val = va_arg(ap, int); @@ -222,14 +222,14 @@ int main(int unused_argc, char **argv) htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_INT, ATTR_NAME_INT, 4711, ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee", ATTR_TYPE_HASH, table, ATTR_TYPE_END); attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_INT, ATTR_NAME_INT, 4711, ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee", diff --git a/postfix/src/util/attr_print64.c b/postfix/src/util/attr_print64.c index 46aaa7631..f9cd51e0a 100644 --- a/postfix/src/util/attr_print64.c +++ b/postfix/src/util/attr_print64.c @@ -44,7 +44,7 @@ /* .IP type /* The type determines the arguments that follow. /* .RS -/* .IP "ATTR_TYPE_NUM (char *, int)" +/* .IP "ATTR_TYPE_INT (char *, int)" /* This argument is followed by an attribute name and an integer. /* .IP "ATTR_TYPE_LONG (char *, long)" /* This argument is followed by an attribute name and a long integer. @@ -164,7 +164,7 @@ int attr_vprint64(VSTREAM *fp, int flags, va_list ap) */ while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { switch (attr_type) { - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: attr_name = va_arg(ap, char *); attr_print64_str(fp, attr_name, strlen(attr_name)); int_val = va_arg(ap, int); @@ -261,14 +261,14 @@ int main(int unused_argc, char **argv) htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_INT, ATTR_NAME_INT, 4711, ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee", ATTR_TYPE_HASH, table, ATTR_TYPE_END); attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_INT, ATTR_NAME_INT, 4711, ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee", diff --git a/postfix/src/util/attr_print_plain.c b/postfix/src/util/attr_print_plain.c index aea66b5c4..61106f7e3 100644 --- a/postfix/src/util/attr_print_plain.c +++ b/postfix/src/util/attr_print_plain.c @@ -44,7 +44,7 @@ /* .IP type /* The type determines the arguments that follow. /* .RS -/* .IP "ATTR_TYPE_NUM (char *, int)" +/* .IP "ATTR_TYPE_INT (char *, int)" /* This argument is followed by an attribute name and an integer. /* .IP "ATTR_TYPE_LONG (char *, long)" /* This argument is followed by an attribute name and a long integer. @@ -131,7 +131,7 @@ int attr_vprint_plain(VSTREAM *fp, int flags, va_list ap) */ while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { switch (attr_type) { - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: attr_name = va_arg(ap, char *); int_val = va_arg(ap, int); vstream_fprintf(fp, "%s=%u\n", attr_name, (unsigned) int_val); @@ -216,14 +216,14 @@ int main(int unused_argc, char **argv) htable_enter(table, "foo-name", mystrdup("foo-value")); htable_enter(table, "bar-name", mystrdup("bar-value")); attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_INT, ATTR_NAME_INT, 4711, ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee", ATTR_TYPE_HASH, table, ATTR_TYPE_END); attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_INT, ATTR_NAME_INT, 4711, ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234, ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee", diff --git a/postfix/src/util/attr_scan0.c b/postfix/src/util/attr_scan0.c index db1f1fa00..8297e7a18 100644 --- a/postfix/src/util/attr_scan0.c +++ b/postfix/src/util/attr_scan0.c @@ -85,7 +85,7 @@ /* .IP type /* The type argument determines the arguments that follow. /* .RS -/* .IP "ATTR_TYPE_NUM (char *, int *)" +/* .IP "ATTR_TYPE_INT (char *, int *)" /* This argument is followed by an attribute name and an integer pointer. /* .IP "ATTR_TYPE_LONG (char *, long *)" /* This argument is followed by an attribute name and a long pointer. @@ -354,7 +354,7 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap) * Do the requested conversion. */ switch (wanted_type) { - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: number = va_arg(ap, unsigned int *); if ((ch = attr_scan0_number(fp, number, str_buf, "input attribute value")) < 0) @@ -447,13 +447,13 @@ int main(int unused_argc, char **used_argv) msg_vstream_init(used_argv[0], VSTREAM_ERR); if ((ret = attr_scan0(VSTREAM_IN, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_INT, ATTR_NAME_INT, &int_val, ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, ATTR_TYPE_STR, ATTR_NAME_STR, str_val, ATTR_TYPE_DATA, ATTR_NAME_DATA, data_val, ATTR_TYPE_HASH, table, ATTR_TYPE_END)) > 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %d\n", ATTR_NAME_INT, int_val); vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); vstream_printf("%s %s\n", ATTR_NAME_DATA, STR(str_val)); @@ -466,12 +466,12 @@ int main(int unused_argc, char **used_argv) } if ((ret = attr_scan0(VSTREAM_IN, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_INT, ATTR_NAME_INT, &int_val, ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, ATTR_TYPE_STR, ATTR_NAME_STR, str_val, ATTR_TYPE_DATA, ATTR_NAME_DATA, data_val, ATTR_TYPE_END)) == 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %d\n", ATTR_NAME_INT, int_val); vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); vstream_printf("%s %s\n", ATTR_NAME_DATA, STR(data_val)); diff --git a/postfix/src/util/attr_scan64.c b/postfix/src/util/attr_scan64.c index 2d5b6936f..d148e6d8f 100644 --- a/postfix/src/util/attr_scan64.c +++ b/postfix/src/util/attr_scan64.c @@ -87,7 +87,7 @@ /* .IP type /* The type argument determines the arguments that follow. /* .RS -/* .IP "ATTR_TYPE_NUM (char *, int *)" +/* .IP "ATTR_TYPE_INT (char *, int *)" /* This argument is followed by an attribute name and an integer pointer. /* .IP "ATTR_TYPE_LONG (char *, long *)" /* This argument is followed by an attribute name and a long pointer. @@ -363,7 +363,7 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap) * elements. */ switch (wanted_type) { - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: if (ch != ':') { msg_warn("missing value for number attribute %s from %s", STR(name_buf), VSTREAM_PATH(fp)); @@ -506,13 +506,13 @@ int main(int unused_argc, char **used_argv) msg_vstream_init(used_argv[0], VSTREAM_ERR); if ((ret = attr_scan64(VSTREAM_IN, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_INT, ATTR_NAME_INT, &int_val, ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, ATTR_TYPE_STR, ATTR_NAME_STR, str_val, ATTR_TYPE_DATA, ATTR_NAME_DATA, data_val, ATTR_TYPE_HASH, table, ATTR_TYPE_END)) > 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %d\n", ATTR_NAME_INT, int_val); vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); vstream_printf("%s %s\n", ATTR_NAME_DATA, STR(data_val)); @@ -525,12 +525,12 @@ int main(int unused_argc, char **used_argv) } if ((ret = attr_scan64(VSTREAM_IN, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_INT, ATTR_NAME_INT, &int_val, ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, ATTR_TYPE_STR, ATTR_NAME_STR, str_val, ATTR_TYPE_DATA, ATTR_NAME_DATA, data_val, ATTR_TYPE_END)) == 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %d\n", ATTR_NAME_INT, int_val); vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); vstream_printf("%s %s\n", ATTR_NAME_DATA, STR(data_val)); @@ -544,6 +544,7 @@ int main(int unused_argc, char **used_argv) if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); + vstring_free(data_val); vstring_free(str_val); htable_free(table, myfree); diff --git a/postfix/src/util/attr_scan_plain.c b/postfix/src/util/attr_scan_plain.c index 70f216e6a..2d8f1a288 100644 --- a/postfix/src/util/attr_scan_plain.c +++ b/postfix/src/util/attr_scan_plain.c @@ -85,7 +85,7 @@ /* .IP type /* The type argument determines the arguments that follow. /* .RS -/* .IP "ATTR_TYPE_NUM (char *, int *)" +/* .IP "ATTR_TYPE_INT (char *, int *)" /* This argument is followed by an attribute name and an integer pointer. /* .IP "ATTR_TYPE_LONG (char *, long *)" /* This argument is followed by an attribute name and a long pointer. @@ -371,7 +371,7 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap) * Do the requested conversion. */ switch (wanted_type) { - case ATTR_TYPE_NUM: + case ATTR_TYPE_INT: if (ch != '=') { msg_warn("missing value for number attribute %s from %s", STR(name_buf), VSTREAM_PATH(fp)); @@ -489,13 +489,13 @@ int main(int unused_argc, char **used_argv) msg_vstream_init(used_argv[0], VSTREAM_ERR); if ((ret = attr_scan_plain(VSTREAM_IN, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_INT, ATTR_NAME_INT, &int_val, ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, ATTR_TYPE_STR, ATTR_NAME_STR, str_val, ATTR_TYPE_DATA, ATTR_NAME_DATA, data_val, ATTR_TYPE_HASH, table, ATTR_TYPE_END)) > 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %d\n", ATTR_NAME_INT, int_val); vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); vstream_printf("%s %s\n", ATTR_NAME_DATA, STR(data_val)); @@ -508,12 +508,12 @@ int main(int unused_argc, char **used_argv) } if ((ret = attr_scan_plain(VSTREAM_IN, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_INT, ATTR_NAME_INT, &int_val, ATTR_TYPE_LONG, ATTR_NAME_LONG, &long_val, ATTR_TYPE_STR, ATTR_NAME_STR, str_val, ATTR_TYPE_DATA, ATTR_NAME_DATA, data_val, ATTR_TYPE_END)) == 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %d\n", ATTR_NAME_INT, int_val); vstream_printf("%s %ld\n", ATTR_NAME_LONG, long_val); vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); vstream_printf("%s %s\n", ATTR_NAME_DATA, STR(data_val)); @@ -527,6 +527,7 @@ int main(int unused_argc, char **used_argv) if (vstream_fflush(VSTREAM_OUT) != 0) msg_fatal("write error: %m"); + vstring_free(data_val); vstring_free(str_val); htable_free(table, myfree); diff --git a/postfix/src/util/auto_clnt.c b/postfix/src/util/auto_clnt.c index c608c6c28..626531cc0 100644 --- a/postfix/src/util/auto_clnt.c +++ b/postfix/src/util/auto_clnt.c @@ -18,6 +18,9 @@ /* void auto_clnt_recover(auto_clnt) /* AUTO_CLNT *auto_clnt; /* +/* const char *auto_clnt_name(auto_clnt) +/* AUTO_CLNT *auto_clnt; +/* /* void auto_clnt_free(auto_clnt) /* AUTO_CLNT *auto_clnt; /* DESCRIPTION @@ -40,6 +43,8 @@ /* auto_clnt_recover() recovers from a server-initiated disconnect /* that happened in the middle of an I/O operation. /* +/* auto_clnt_name() returns the name of the specified client endpoint. +/* /* auto_clnt_free() destroys of the specified client endpoint. /* /* Arguments: @@ -293,6 +298,13 @@ AUTO_CLNT *auto_clnt_create(const char *service, int timeout, return (auto_clnt); } +/* auto_clnt_name - return client stream name */ + +const char *auto_clnt_name(AUTO_CLNT *auto_clnt) +{ + return (auto_clnt->endpoint); +} + /* auto_clnt_free - destroy client stream instance */ void auto_clnt_free(AUTO_CLNT *auto_clnt) diff --git a/postfix/src/util/auto_clnt.h b/postfix/src/util/auto_clnt.h index 458c5f937..a168c1adc 100644 --- a/postfix/src/util/auto_clnt.h +++ b/postfix/src/util/auto_clnt.h @@ -24,6 +24,7 @@ typedef struct AUTO_CLNT AUTO_CLNT; extern AUTO_CLNT *auto_clnt_create(const char *, int, int, int); extern VSTREAM *auto_clnt_access(AUTO_CLNT *); extern void auto_clnt_recover(AUTO_CLNT *); +extern const char *auto_clnt_name(AUTO_CLNT *); extern void auto_clnt_free(AUTO_CLNT *); /* LICENSE diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index e57df6506..b39a97154 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -56,6 +56,9 @@ /* void dict_load_fp(dict_name, fp) /* const char *dict_name; /* VSTREAM *fp; +/* +/* const char *dict_flags_str(dict_flags) +/* int dict_flags; /* DESCRIPTION /* This module maintains a collection of name-value dictionaries. /* Each dictionary has its own name and has its own methods to read @@ -141,6 +144,10 @@ /* /* dict_load_fp() reads name-value entries from an open stream. /* It has the same semantics as the dict_load_file() function. +/* +/* dict_flags_str() returns a printable representation of the +/* specified dictionary flags. The result is overwritten upon +/* each call. /* SEE ALSO /* htable(3) /* BUGS @@ -186,6 +193,7 @@ #include "mac_expand.h" #include "stringops.h" #include "iostuff.h" +#include "name_mask.h" #include "dict.h" #include "dict_ht.h" @@ -507,3 +515,37 @@ int dict_changed(void) { return (dict_changed_name() != 0); } + + /* + * Mapping between flag names and flag values. + */ +static NAME_MASK dict_mask[] = { + "warn_dup", (1 << 0), /* if file, warn about dups */ + "ignore_dup", (1 << 1), /* if file, ignore dups */ + "try0null", (1 << 2), /* do not append 0 to key/value */ + "try1null", (1 << 3), /* append 0 to key/value */ + "fixed", (1 << 4), /* fixed key map */ + "pattern", (1 << 5), /* keys are patterns */ + "lock", (1 << 6), /* lock before access */ + "replace", (1 << 7), /* if file, replace dups */ + "sync_update", (1 << 8), /* if file, sync updates */ + "debug", (1 << 9), /* log access */ + "no_regsub", (1 << 11), /* disallow regexp substitution */ + "no_proxy", (1 << 12), /* disallow proxy mapping */ + "no_unauth", (1 << 13), /* disallow unauthenticated data */ + "fold_fix", (1 << 14), /* case-fold with fixed-case key map */ + "fold_mul", (1 << 15), /* case-fold with multi-case key map */ +}; + +/* dict_flags_str - convert mask to string for debugging purposes */ + +const char *dict_flags_str(int dict_flags) +{ + static VSTRING *buf = 0; + + if (buf == 0) + buf = vstring_alloc(1); + + return (str_name_mask_opt(buf, "dictionary flags", dict_mask, dict_flags, + NAME_MASK_RETURN | NAME_MASK_PIPE)); +} diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h index 9532fec0b..eadc7733f 100644 --- a/postfix/src/util/dict.h +++ b/postfix/src/util/dict.h @@ -21,6 +21,7 @@ */ #include #include +#include /* * Generic dictionary interface - in reality, a dictionary extends this @@ -38,6 +39,7 @@ typedef struct DICT { int lock_fd; /* for dict_update() lock */ int stat_fd; /* change detection */ time_t mtime; /* mod time at open */ + VSTRING *fold_buf; /* key folding buffer */ } DICT; extern DICT *dict_alloc(const char *, const char *, ssize_t); @@ -57,10 +59,15 @@ extern DICT *dict_debug(DICT *); #define DICT_FLAG_DUP_REPLACE (1<<7) /* if file, replace dups */ #define DICT_FLAG_SYNC_UPDATE (1<<8) /* if file, sync updates */ #define DICT_FLAG_DEBUG (1<<9) /* log access */ -#define DICT_FLAG_FOLD_KEY (1<<10) /* lowercase the lookup key */ +/*#define DICT_FLAG_FOLD_KEY (1<<10) /* lowercase the lookup key */ #define DICT_FLAG_NO_REGSUB (1<<11) /* disallow regexp substitution */ #define DICT_FLAG_NO_PROXY (1<<12) /* disallow proxy mapping */ #define DICT_FLAG_NO_UNAUTH (1<<13) /* disallow unauthenticated data */ +#define DICT_FLAG_FOLD_FIX (1<<14) /* case-fold key with fixed-case map */ +#define DICT_FLAG_FOLD_MUL (1<<15) /* case-fold key with multi-case map */ +#define DICT_FLAG_FOLD_ANY (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL) + + /* IMPORTANT: Update the dict_mask[] table when the above changes */ #define DICT_FLAG_PARANOID \ (DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH) @@ -112,6 +119,7 @@ typedef void (*DICT_WALK_ACTION) (const char *, DICT *, char *); extern void dict_walk(DICT_WALK_ACTION, char *); extern int dict_changed(void); extern const char *dict_changed_name(void); +extern const char *dict_flags_str(int); /* LICENSE /* .ad diff --git a/postfix/src/util/dict_alloc.c b/postfix/src/util/dict_alloc.c index 5d9dc83a6..9c08a9071 100644 --- a/postfix/src/util/dict_alloc.c +++ b/postfix/src/util/dict_alloc.c @@ -100,7 +100,7 @@ static int dict_default_sequence(DICT *dict, int unused_function, static void dict_default_close(DICT *dict) { msg_fatal("%s table %s: close operation is not supported", - dict->type, dict->name); + dict->type, dict->name); } /* dict_alloc - allocate dictionary object, initialize super-class */ @@ -120,6 +120,7 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size) dict->lock_fd = -1; dict->stat_fd = -1; dict->mtime = 0; + dict->fold_buf = 0; return dict; } diff --git a/postfix/src/util/dict_cdb.c b/postfix/src/util/dict_cdb.c index 6d8d11c8d..1aa67a3fd 100644 --- a/postfix/src/util/dict_cdb.c +++ b/postfix/src/util/dict_cdb.c @@ -57,6 +57,7 @@ #include "stringops.h" #include "iostuff.h" #include "myflock.h" +#include "stringops.h" #include "dict.h" #include "dict_cdb.h" @@ -106,6 +107,14 @@ static const char *dict_cdbq_lookup(DICT *dict, const char *name) /* CDB is constant, so do not try to acquire a lock. */ + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * See if this CDB file was written with one null byte appended to key * and value. @@ -156,6 +165,8 @@ static void dict_cdbq_close(DICT *dict) cdb_free(&dict_cdbq->cdb); close(dict->stat_fd); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -205,6 +216,8 @@ static DICT *dict_cdbq_open(const char *path, int dict_flags) if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) dict_flags |= DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL; dict_cdbq->dict.flags = dict_flags | DICT_FLAG_FIXED; + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_cdbq->dict.fold_buf = vstring_alloc(10); myfree(cdb_path); return (&dict_cdbq->dict); @@ -218,6 +231,14 @@ static void dict_cdbm_update(DICT *dict, const char *name, const char *value) unsigned ksize, vsize; int r; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + ksize = strlen(name); vsize = strlen(value); @@ -282,6 +303,8 @@ static void dict_cdbm_close(DICT *dict) msg_fatal("close database %s: %m", dict_cdbm->cdb_path); myfree(dict_cdbm->cdb_path); myfree(dict_cdbm->tmp_path); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -358,6 +381,8 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags) && (dict_flags & DICT_FLAG_TRY0NULL)) dict_flags &= ~DICT_FLAG_TRY0NULL; dict_cdbm->dict.flags = dict_flags | DICT_FLAG_FIXED; + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_cdbm->dict.fold_buf = vstring_alloc(10); return (&dict_cdbm->dict); } diff --git a/postfix/src/util/dict_db.c b/postfix/src/util/dict_db.c index 586cb4247..24142fcde 100644 --- a/postfix/src/util/dict_db.c +++ b/postfix/src/util/dict_db.c @@ -190,6 +190,14 @@ static const char *dict_db_lookup(DICT *dict, const char *name) memset(&db_key, 0, sizeof(db_key)); memset(&db_value, 0, sizeof(db_value)); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * Acquire a shared lock. */ @@ -253,6 +261,14 @@ static void dict_db_update(DICT *dict, const char *name, const char *value) if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) msg_panic("dict_db_update: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + memset(&db_key, 0, sizeof(db_key)); memset(&db_value, 0, sizeof(db_value)); db_key.data = (void *) name; @@ -330,6 +346,14 @@ static int dict_db_delete(DICT *dict, const char *name) if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) msg_panic("dict_db_delete: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + memset(&db_key, 0, sizeof(db_key)); /* @@ -512,6 +536,8 @@ static void dict_db_close(DICT *dict) vstring_free(dict_db->key_buf); if (dict_db->val_buf) vstring_free(dict_db->val_buf); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -678,6 +704,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags, dict_db->dict.flags = dict_flags | DICT_FLAG_FIXED; if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) dict_db->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL); + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_db->dict.fold_buf = vstring_alloc(10); dict_db->db = db; #if DB_VERSION_MAJOR > 1 dict_db->cursor = 0; diff --git a/postfix/src/util/dict_dbm.c b/postfix/src/util/dict_dbm.c index 87e527694..29489946b 100644 --- a/postfix/src/util/dict_dbm.c +++ b/postfix/src/util/dict_dbm.c @@ -90,6 +90,14 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name) dict_errno = 0; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * Acquire an exclusive lock. */ @@ -150,6 +158,14 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value) if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) msg_panic("dict_dbm_update: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + dbm_key.dptr = (void *) name; dbm_value.dptr = (void *) value; dbm_key.dsize = strlen(name); @@ -220,6 +236,14 @@ static int dict_dbm_delete(DICT *dict, const char *name) if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) msg_panic("dict_dbm_delete: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * Acquire an exclusive lock. */ @@ -362,6 +386,8 @@ static void dict_dbm_close(DICT *dict) vstring_free(dict_dbm->key_buf); if (dict_dbm->val_buf) vstring_free(dict_dbm->val_buf); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -431,6 +457,8 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags) dict_dbm->dict.flags = dict_flags | DICT_FLAG_FIXED; if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0) dict_dbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL); + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_dbm->dict.fold_buf = vstring_alloc(10); dict_dbm->dbm = dbm; dict_dbm->key_buf = 0; dict_dbm->val_buf = 0; diff --git a/postfix/src/util/dict_env.c b/postfix/src/util/dict_env.c index e87ac15a9..eb5b6a582 100644 --- a/postfix/src/util/dict_env.c +++ b/postfix/src/util/dict_env.c @@ -42,23 +42,39 @@ #include "mymalloc.h" #include "msg.h" #include "safe.h" +#include "stringops.h" #include "dict.h" #include "dict_env.h" /* dict_env_update - update environment array */ -static void dict_env_update(DICT *unused_dict, const char *name, const char *value) +static void dict_env_update(DICT *dict, const char *name, const char *value) { + + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } if (setenv(name, value, 1)) msg_fatal("setenv: %m"); } /* dict_env_lookup - access environment array */ -static const char *dict_env_lookup(DICT *unused_dict, const char *name) +static const char *dict_env_lookup(DICT *dict, const char *name) { dict_errno = 0; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } return (safe_getenv(name)); } @@ -66,6 +82,8 @@ static const char *dict_env_lookup(DICT *unused_dict, const char *name) static void dict_env_close(DICT *dict) { + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -80,5 +98,7 @@ DICT *dict_env_open(const char *name, int unused_flags, int dict_flags) dict->update = dict_env_update; dict->close = dict_env_close; dict->flags = dict_flags | DICT_FLAG_FIXED; - return (DICT_DEBUG(dict)); + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict->fold_buf = vstring_alloc(10); + return (DICT_DEBUG (dict)); } diff --git a/postfix/src/util/dict_ni.c b/postfix/src/util/dict_ni.c index c6497f888..c0cbd12fb 100644 --- a/postfix/src/util/dict_ni.c +++ b/postfix/src/util/dict_ni.c @@ -44,6 +44,7 @@ #include "dict_ni.h" #include "msg.h" #include "mymalloc.h" +#include "stringops.h" typedef struct { DICT dict; /* my super */ @@ -149,6 +150,13 @@ static const char *dict_ni_lookup(DICT *dict, const char *key) { DICT_NI *d = (DICT_NI *) dict; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, key); + key = lowercase(vstring_str(dict->fold_buf)); + } return dict_ni_do_lookup(d->dict.name, NETINFO_PROP_KEY, key, NETINFO_PROP_VALUE); } @@ -159,6 +167,8 @@ static void dict_ni_close(DICT *dict) { DICT_NI *d = (DICT_NI *) dict; + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -171,6 +181,8 @@ DICT *dict_ni_open(const char *path, int unused_flags, int dict_flags) d->dict.lookup = dict_ni_lookup; d->dict.close = dict_ni_close; d->dict.flags = dict_flags | DICT_FLAG_FIXED; + if (dict_flags & DICT_FLAG_FOLD_FIX) + d->dict.fold_buf = vstring_alloc(10); return (DICT_DEBUG (&d->dict)); } diff --git a/postfix/src/util/dict_nis.c b/postfix/src/util/dict_nis.c index 104fa8f14..da61f07af 100644 --- a/postfix/src/util/dict_nis.c +++ b/postfix/src/util/dict_nis.c @@ -54,6 +54,7 @@ #include "msg.h" #include "mymalloc.h" #include "vstring.h" +#include "stringops.h" #include "dict.h" #include "dict_nis.h" @@ -153,6 +154,14 @@ static const char *dict_nis_lookup(DICT *dict, const char *key) if (dict_nis_domain == dict_nis_disabled) return (0); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, key); + key = lowercase(vstring_str(dict->fold_buf)); + } + /* * See if this NIS map was written with one null byte appended to key and * value. @@ -202,6 +211,8 @@ static const char *dict_nis_lookup(DICT *dict, const char *key) static void dict_nis_close(DICT *dict) { + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -221,6 +232,8 @@ DICT *dict_nis_open(const char *map, int open_flags, int dict_flags) dict_nis->dict.flags = dict_flags | DICT_FLAG_FIXED; if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL); + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_nis->dict.fold_buf = vstring_alloc(10); if (dict_nis_domain == 0) dict_nis_init(); return (DICT_DEBUG (&dict_nis->dict)); diff --git a/postfix/src/util/dict_nisplus.c b/postfix/src/util/dict_nisplus.c index 2f1a45772..87163ac2c 100644 --- a/postfix/src/util/dict_nisplus.c +++ b/postfix/src/util/dict_nisplus.c @@ -136,6 +136,14 @@ static const char *dict_nisplus_lookup(DICT *dict, const char *key) quoted_key = vstring_alloc(100); } + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, key); + key = lowercase(vstring_str(dict->fold_buf)); + } + /* * Check that the lookup key does not contain characters disallowed by * nis+(1). @@ -229,6 +237,8 @@ static void dict_nisplus_close(DICT *dict) DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict; myfree(dict_nisplus->template); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -256,6 +266,8 @@ DICT *dict_nisplus_open(const char *map, int open_flags, int dict_flags) dict_nisplus->dict.lookup = dict_nisplus_lookup; dict_nisplus->dict.close = dict_nisplus_close; dict_nisplus->dict.flags = dict_flags | DICT_FLAG_FIXED; + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_nisplus->dict.fold_buf = vstring_alloc(10); /* * Convert the query template into an indexed name and column number. The diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c index c89911f54..e52c87255 100644 --- a/postfix/src/util/dict_open.c +++ b/postfix/src/util/dict_open.c @@ -80,6 +80,17 @@ /* .IP DICT_FLAG_LOCK /* With maps where this is appropriate, acquire an exclusive lock /* before writing, and acquire a shared lock before reading. +/* .IP DICT_FLAG_FOLD_FIX +/* With databases whose lookup fields are fixed-case strings, +/* fold the search key to lower case before accessing the +/* database. This includes hash:, cdb:, dbm:. nis:, ldap:, +/* *sql. +/* .IP DICT_FLAG_FOLD_MUL +/* With databases where one lookup field can match both upper +/* and lower case, fold the search key to lower case before +/* accessing the database. This includes regexp: and pcre: +/* .IP DICT_FLAG_FOLD_ANY +/* Short-hand for (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL). /* .IP DICT_FLAG_SYNC_UPDATE /* With file-based maps, flush I/O buffers to file after each update. /* Thus feature is not supported with some file-based dictionaries. @@ -371,7 +382,7 @@ ARGV *dict_mapnames() static NORETURN usage(char *myname) { - msg_fatal("usage: %s type:file read|write|create", myname); + msg_fatal("usage: %s type:file read|write|create [fold]", myname); } int main(int argc, char **argv) @@ -386,6 +397,7 @@ int main(int argc, char **argv) const char *key; const char *value; int ch; + int dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE; signal(SIGPIPE, SIG_IGN); @@ -400,7 +412,7 @@ int main(int argc, char **argv) } } optind = OPTIND; - if (argc - optind != 2) + if (argc - optind < 2 || argc - optind > 3) usage(argv[0]); if (strcasecmp(argv[optind + 1], "create") == 0) open_flags = O_CREAT | O_RDWR | O_TRUNC; @@ -410,8 +422,10 @@ int main(int argc, char **argv) open_flags = O_RDONLY; else msg_fatal("unknown access mode: %s", argv[2]); + if (argv[optind + 2] && strcasecmp(argv[optind + 2], "fold") == 0) + dict_flags |= DICT_FLAG_FOLD_ANY; dict_name = argv[optind]; - dict = dict_open(dict_name, open_flags, DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE); + dict = dict_open(dict_name, open_flags, dict_flags); dict_register(dict_name, dict); while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { bufp = vstring_str(inbuf); diff --git a/postfix/src/util/dict_pcre.c b/postfix/src/util/dict_pcre.c index c706f522f..8a4d9ae62 100644 --- a/postfix/src/util/dict_pcre.c +++ b/postfix/src/util/dict_pcre.c @@ -182,7 +182,7 @@ static int dict_pcre_expand(int type, VSTRING *buf, char *ptr) dict_pcre->dict.name, match_rule->rule.lineno); else msg_fatal("regexp %s, line %d: pcre_get_substring error: %d", - dict_pcre->dict.name, match_rule->rule.lineno, ret); + dict_pcre->dict.name, match_rule->rule.lineno, ret); } if (*pp == 0) { myfree((char *) pp); @@ -207,7 +207,7 @@ static int dict_pcre_expand(int type, VSTRING *buf, char *ptr) static void dict_pcre_exec_error(const char *mapname, int lineno, int errval) { switch (errval) { - case 0: + case 0: msg_warn("pcre map %s, line %d: too many (...)", mapname, lineno); return; @@ -262,6 +262,13 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) if (msg_verbose) msg_info("dict_pcre_lookup: %s: %s", dict->name, lookup_string); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, lookup_string); + lookup_string = lowercase(vstring_str(dict->fold_buf)); + } for (rule = dict_pcre->head; rule; rule = rule->next) { /* @@ -399,6 +406,8 @@ static void dict_pcre_close(DICT *dict) } if (dict_pcre->expansion_buf) vstring_free(dict_pcre->expansion_buf); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -662,9 +671,9 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, sizeof(DICT_PCRE_MATCH_RULE)); match_rule->match = regexp.match; match_rule->max_sub = prescan_context.max_sub; - if (prescan_context.literal) - match_rule->replacement = prescan_context.literal; - else + if (prescan_context.literal) + match_rule->replacement = prescan_context.literal; + else match_rule->replacement = mystrdup(p); match_rule->pattern = engine.pattern; match_rule->hints = engine.hints; @@ -780,6 +789,8 @@ DICT *dict_pcre_open(const char *mapname, int unused_flags, int dict_flags) dict_pcre->dict.lookup = dict_pcre_lookup; dict_pcre->dict.close = dict_pcre_close; dict_pcre->dict.flags = dict_flags | DICT_FLAG_PATTERN; + if (dict_flags & DICT_FLAG_FOLD_MUL) + dict_pcre->dict.fold_buf = vstring_alloc(10); dict_pcre->head = 0; dict_pcre->expansion_buf = 0; diff --git a/postfix/src/util/dict_regexp.c b/postfix/src/util/dict_regexp.c index f56a7ea59..b0f1d9768 100644 --- a/postfix/src/util/dict_regexp.c +++ b/postfix/src/util/dict_regexp.c @@ -221,6 +221,13 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) if (msg_verbose) msg_info("dict_regexp_lookup: %s: %s", dict->name, lookup_string); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, lookup_string); + lookup_string = lowercase(vstring_str(dict->fold_buf)); + } for (rule = dict_regexp->head; rule; rule = rule->next) { /* @@ -351,6 +358,8 @@ static void dict_regexp_close(DICT *dict) myfree((char *) dict_regexp->pmatch); if (dict_regexp->expansion_buf) vstring_free(dict_regexp->expansion_buf); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -612,13 +621,13 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, * result string, or when the highest numbered substring is less than * the total number of () subpatterns. */ - if (prescan_context.max_sub == 0) + if (prescan_context.max_sub == 0) first_pat.options |= REG_NOSUB; if (prescan_context.max_sub > 0 && first_pat.match == 0) { msg_warn("regexp map %s, line %d: $number found in negative match " "replacement text: skipping this rule", mapname, lineno); CREATE_MATCHOP_ERROR_RETURN(0); - } + } if (prescan_context.max_sub > 0 && (dict_flags & DICT_FLAG_NO_REGSUB)) { msg_warn("regexp map %s, line %d: " "regular expression substitution is not allowed: " @@ -738,6 +747,8 @@ DICT *dict_regexp_open(const char *mapname, int unused_flags, int dict_flags) dict_regexp->dict.lookup = dict_regexp_lookup; dict_regexp->dict.close = dict_regexp_close; dict_regexp->dict.flags = dict_flags | DICT_FLAG_PATTERN; + if (dict_flags & DICT_FLAG_FOLD_MUL) + dict_regexp->dict.fold_buf = vstring_alloc(10); dict_regexp->head = 0; dict_regexp->pmatch = 0; dict_regexp->expansion_buf = 0; diff --git a/postfix/src/util/dict_sdbm.c b/postfix/src/util/dict_sdbm.c index 35ee7782e..8c6085d64 100644 --- a/postfix/src/util/dict_sdbm.c +++ b/postfix/src/util/dict_sdbm.c @@ -84,6 +84,14 @@ static const char *dict_sdbm_lookup(DICT *dict, const char *name) dict_errno = 0; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * Acquire an exclusive lock. */ @@ -144,6 +152,14 @@ static void dict_sdbm_update(DICT *dict, const char *name, const char *value) if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) msg_panic("dict_sdbm_update: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + dbm_key.dptr = (void *) name; dbm_value.dptr = (void *) value; dbm_key.dsize = strlen(name); @@ -214,6 +230,14 @@ static int dict_sdbm_delete(DICT *dict, const char *name) if ((dict->flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0) msg_panic("dict_sdbm_delete: no DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL flag"); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + /* * Acquire an exclusive lock. */ @@ -357,6 +381,8 @@ static void dict_sdbm_close(DICT *dict) vstring_free(dict_sdbm->key_buf); if (dict_sdbm->val_buf) vstring_free(dict_sdbm->val_buf); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -424,6 +450,8 @@ DICT *dict_sdbm_open(const char *path, int open_flags, int dict_flags) dict_sdbm->dict.flags = dict_flags | DICT_FLAG_FIXED; if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0) dict_sdbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL); + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_sdbm->dict.fold_buf = vstring_alloc(10); dict_sdbm->dbm = dbm; dict_sdbm->key_buf = 0; dict_sdbm->val_buf = 0; diff --git a/postfix/src/util/dict_tcp.c b/postfix/src/util/dict_tcp.c index 2da83feb5..1e8d2bc10 100644 --- a/postfix/src/util/dict_tcp.c +++ b/postfix/src/util/dict_tcp.c @@ -164,6 +164,13 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key) if (msg_verbose) msg_info("%s: key %s", myname, key); + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, key); + key = lowercase(vstring_str(dict->fold_buf)); + } for (tries = 0; /* see below */ ; /* see below */ ) { /* @@ -266,6 +273,8 @@ static void dict_tcp_close(DICT *dict) vstring_free(dict_tcp->raw_buf); if (dict_tcp->hex_buf) vstring_free(dict_tcp->hex_buf); + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -297,6 +306,8 @@ DICT *dict_tcp_open(const char *map, int open_flags, int dict_flags) dict_tcp->dict.lookup = dict_tcp_lookup; dict_tcp->dict.close = dict_tcp_close; dict_tcp->dict.flags = dict_flags | DICT_FLAG_PATTERN; + if (dict_flags & DICT_FLAG_FOLD_MUL) + dict_tcp->dict.fold_buf = vstring_alloc(10); return (DICT_DEBUG (&dict_tcp->dict)); } diff --git a/postfix/src/util/dict_unix.c b/postfix/src/util/dict_unix.c index 60c776d50..ed50c1915 100644 --- a/postfix/src/util/dict_unix.c +++ b/postfix/src/util/dict_unix.c @@ -51,6 +51,7 @@ #include "msg.h" #include "mymalloc.h" #include "vstring.h" +#include "stringops.h" #include "dict.h" #include "dict_unix.h" @@ -62,7 +63,7 @@ typedef struct { /* dict_unix_getpwnam - find password table entry */ -static const char *dict_unix_getpwnam(DICT *unused_dict, const char *key) +static const char *dict_unix_getpwnam(DICT *dict, const char *key) { struct passwd *pwd; static VSTRING *buf; @@ -70,6 +71,13 @@ static const char *dict_unix_getpwnam(DICT *unused_dict, const char *key) dict_errno = 0; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, key); + key = lowercase(vstring_str(dict->fold_buf)); + } if ((pwd = getpwnam(key)) == 0) { if (sanity_checked == 0) { sanity_checked = 1; @@ -94,7 +102,7 @@ static const char *dict_unix_getpwnam(DICT *unused_dict, const char *key) /* dict_unix_getgrnam - find group table entry */ -static const char *dict_unix_getgrnam(DICT *unused_dict, const char *key) +static const char *dict_unix_getgrnam(DICT *dict, const char *key) { struct group *grp; static VSTRING *buf; @@ -103,6 +111,13 @@ static const char *dict_unix_getgrnam(DICT *unused_dict, const char *key) dict_errno = 0; + /* + * Optionally fold the key. + */ + if (dict->fold_buf) { + vstring_strcpy(dict->fold_buf, key); + key = lowercase(vstring_str(dict->fold_buf)); + } if ((grp = getgrnam(key)) == 0) { if (sanity_checked == 0) { sanity_checked = 1; @@ -133,6 +148,8 @@ static const char *dict_unix_getgrnam(DICT *unused_dict, const char *key) static void dict_unix_close(DICT *dict) { + if (dict->fold_buf) + vstring_free(dict->fold_buf); dict_free(dict); } @@ -165,5 +182,8 @@ DICT *dict_unix_open(const char *map, int unused_flags, int dict_flags) dict_unix->dict.lookup = lp->lookup; dict_unix->dict.close = dict_unix_close; dict_unix->dict.flags = dict_flags | DICT_FLAG_FIXED; + if (dict_flags & DICT_FLAG_FOLD_FIX) + dict_unix->dict.fold_buf = vstring_alloc(10); + return (DICT_DEBUG (&dict_unix->dict)); } diff --git a/postfix/src/util/htable.c b/postfix/src/util/htable.c index e113e6a4c..86116e1e0 100644 --- a/postfix/src/util/htable.c +++ b/postfix/src/util/htable.c @@ -364,6 +364,9 @@ int main(int unused_argc, char **unused_argv) htable_delete(hash, ht[0]->key, (void (*) (char *)) 0); if (hash->used > 0) msg_panic("%d entries not deleted", hash->used); + myfree((char *) ht_info); + htable_free(hash, (void (*) (char *)) 0); + vstring_free(buf); return (0); } diff --git a/postfix/src/util/match_list.c b/postfix/src/util/match_list.c index fb57b3e1d..f8c60eefa 100644 --- a/postfix/src/util/match_list.c +++ b/postfix/src/util/match_list.c @@ -132,11 +132,12 @@ static ARGV *match_list_parse(ARGV *list, char *string) if (buf == 0) buf = vstring_alloc(10); #define OPEN_FLAGS O_RDONLY -#define DICT_FLAGS DICT_FLAG_LOCK +#define DICT_FLAGS (DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX) #define STR(x) vstring_str(x) for (map_type_name = pattern; *map_type_name == '!'; map_type_name++) /* void */ ; - vstring_sprintf(buf, "%s(%o,%o)", pattern, OPEN_FLAGS, DICT_FLAGS); + vstring_sprintf(buf, "%s(%o,%s)", pattern, OPEN_FLAGS, + dict_flags_str(DICT_FLAGS)); map_type_name_flags = STR(buf) + (map_type_name - pattern); if (dict_handle(map_type_name_flags) == 0) dict_register(map_type_name_flags, diff --git a/postfix/src/util/match_ops.c b/postfix/src/util/match_ops.c index 29eff7e1c..3f9f20eea 100644 --- a/postfix/src/util/match_ops.c +++ b/postfix/src/util/match_ops.c @@ -87,7 +87,6 @@ int match_string(int unused_flags, const char *string, const char *pattern) { char *myname = "match_string"; int match; - char *key; if (msg_verbose) msg_info("%s: %s ~? %s", myname, string, pattern); @@ -96,9 +95,7 @@ int match_string(int unused_flags, const char *string, const char *pattern) * Try dictionary lookup: exact match. */ if (MATCH_DICTIONARY(pattern)) { - key = lowercase(mystrdup(string)); - match = (dict_lookup(pattern, key) != 0); - myfree(key); + match = (dict_lookup(pattern, string) != 0); if (match != 0) return (1); if (dict_errno != 0) @@ -126,30 +123,39 @@ int match_hostname(int flags, const char *name, const char *pattern) char *myname = "match_hostname"; const char *pd; const char *entry; - char *next; - char *temp; + const char *next; int match; + DICT *dict; if (msg_verbose) msg_info("%s: %s ~? %s", myname, name, pattern); /* * Try dictionary lookup: exact match and parent domains. + * + * Don't look up parent domain substrings with regexp maps etc. */ if (MATCH_DICTIONARY(pattern)) { - temp = lowercase(mystrdup(name)); + if ((dict = dict_handle(pattern)) == 0) + msg_panic("%s: unknown dictionary: %s", myname, pattern); match = 0; - for (entry = temp; *entry != 0; entry = next) { - if ((match = (dict_lookup(pattern, entry) != 0)) != 0) - break; - if (dict_errno != 0) - msg_fatal("%s: table lookup problem", pattern); + for (entry = name; *entry != 0; entry = next) { + if (entry == name || (dict->flags & DICT_FLAG_FIXED)) { + match = (dict_get(dict, entry) != 0); + if (msg_verbose > 1) + msg_info("%s: lookup %s:%s %s: %s", + myname, dict->type, dict->name, entry, + match ? "found" : "notfound"); + if (match != 0) + break; + if (dict_errno != 0) + msg_fatal("%s: table lookup problem", pattern); + } if ((next = strchr(entry + 1, '.')) == 0) break; if (flags & MATCH_FLAG_PARENT) next += 1; } - myfree(temp); return (match); } diff --git a/postfix/src/util/myaddrinfo.ref b/postfix/src/util/myaddrinfo.ref index 49d6ed2e0..bc7360101 100644 --- a/postfix/src/util/myaddrinfo.ref +++ b/postfix/src/util/myaddrinfo.ref @@ -1,6 +1,6 @@ ./myaddrinfo: === hostname belly.porcupine.org === -./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2001:240:5c7:0:250:56ff:fe10:bd03 -./myaddrinfo: 2001:240:5c7:0:250:56ff:fe10:bd03 -> belly.porcupine.org +./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2001:240:587:0:250:56ff:fe10:bd03 +./myaddrinfo: 2001:240:587:0:250:56ff:fe10:bd03 -> belly.porcupine.org ./myaddrinfo: belly.porcupine.org -> family=2 sock=1 proto=6 168.100.189.6 ./myaddrinfo: 168.100.189.6 -> belly.porcupine.org ./myaddrinfo: === host address 168.100.189.2 === diff --git a/postfix/src/util/name_mask.c b/postfix/src/util/name_mask.c index 8a2a361ee..d049b9ec2 100644 --- a/postfix/src/util/name_mask.c +++ b/postfix/src/util/name_mask.c @@ -22,7 +22,8 @@ /* const char *names; /* int flags; /* -/* const char *str_name_mask_opt(context, table, mask, flags) +/* const char *str_name_mask_opt(buf, context, table, mask, flags) +/* VSTRING *buf; /* const char *context; /* NAME_MASK *table; /* int mask; @@ -41,6 +42,8 @@ /* with additional fine control. /* /* Arguments: +/* .IP buf +/* Null pointer or pointer to buffer storage. /* .IP context /* What kind of names and /* masks are being manipulated, in order to make error messages @@ -72,6 +75,8 @@ /* it has no effect with str_name_mask(). /* .IP NAME_MASK_COMMA /* Use comma instead of space when converting a mask to string. +/* .IP NAME_MASK_PIPE +/* Use "|" instead of space when converting a mask to string. /* .RE /* The value NAME_MASK_NONE explicitly requests no features, /* and NAME_MASK_DEFAULT enables the default options. @@ -158,18 +163,22 @@ int name_mask_opt(const char *context, NAME_MASK *table, const char *names, /* str_name_mask_opt - mask to string */ -const char *str_name_mask_opt(const char *context, NAME_MASK *table, +const char *str_name_mask_opt(VSTRING *buf, const char *context, + NAME_MASK *table, int mask, int flags) { char *myname = "name_mask"; NAME_MASK *np; int len; - static VSTRING *buf = 0; - int delim = (flags & NAME_MASK_COMMA ? ',' : ' '); - - if (buf == 0) - buf = vstring_alloc(1); + static VSTRING *my_buf = 0; + int delim = (flags & NAME_MASK_COMMA ? ',' : + (flags & NAME_MASK_PIPE ? '|' : ' ')); + if (buf == 0) { + if (my_buf == 0) + my_buf = vstring_alloc(1); + buf = my_buf; + } VSTRING_RESET(buf); for (np = table; mask != 0; np++) { @@ -219,7 +228,8 @@ int main(int argc, char **argv) while (--argc && *++argv) { mask = name_mask("test", table, *argv); vstream_printf("%s -> 0x%x -> %s\n", - *argv, mask, str_name_mask("mask_test", table, mask)); + *argv, mask, str_name_mask((VSTRING *) 0, "mask_test", + table, mask)); vstream_fflush(VSTREAM_OUT); } vstring_free(buf); diff --git a/postfix/src/util/name_mask.h b/postfix/src/util/name_mask.h index 3da7ac27a..423bfae6a 100644 --- a/postfix/src/util/name_mask.h +++ b/postfix/src/util/name_mask.h @@ -11,6 +11,11 @@ /* DESCRIPTION /* .nf + /* + * Utility library. + */ +#include + /* * External interface. */ @@ -23,6 +28,7 @@ typedef struct { #define NAME_MASK_ANY_CASE (1<<1) #define NAME_MASK_RETURN (1<<2) #define NAME_MASK_COMMA (1<<3) +#define NAME_MASK_PIPE (1<<4) #define NAME_MASK_MATCH_REQ NAME_MASK_FATAL @@ -32,10 +38,10 @@ typedef struct { #define name_mask(tag, table, str) \ name_mask_opt((tag), (table), (str), NAME_MASK_DEFAULT) #define str_name_mask(tag, table, mask) \ - str_name_mask_opt((tag), (table), (mask), NAME_MASK_DEFAULT) + str_name_mask_opt(((VSTRING *) 0), (tag), (table), (mask), NAME_MASK_DEFAULT) extern int name_mask_opt(const char *, NAME_MASK *, const char *, int); -extern const char *str_name_mask_opt(const char *, NAME_MASK *, int, int); +extern const char *str_name_mask_opt(VSTRING *, const char *, NAME_MASK *, int, int); /* LICENSE /* .ad diff --git a/postfix/src/util/unescape.c b/postfix/src/util/unescape.c index 27d9d849f..025df5674 100644 --- a/postfix/src/util/unescape.c +++ b/postfix/src/util/unescape.c @@ -188,7 +188,7 @@ int main(int argc, char **argv) VSTRING *out = vstring_alloc(10); int un_escape = 1; - if (argc > 2 || (un_escape = strcmp(argv[1], "-e")) != 0) + if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0) msg_fatal("usage: %s [-e (escape)]", argv[0]); if (un_escape) { diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c index ecc0d5f39..49fccbcb1 100644 --- a/postfix/src/verify/verify.c +++ b/postfix/src/verify/verify.c @@ -305,7 +305,7 @@ static void verify_update_service(VSTREAM *client_stream) if (attr_scan(client_stream, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr, - ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, &addr_status, + ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, &addr_status, ATTR_TYPE_STR, MAIL_ATTR_WHY, text, ATTR_TYPE_END) == 3) { /* FIX 200501 IPv6 patch did not neuter ":" in address literals. */ @@ -314,7 +314,7 @@ static void verify_update_service(VSTREAM *client_stream) msg_warn("bad recipient status %d for recipient %s", addr_status, STR(addr)); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, VRFY_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_BAD, ATTR_TYPE_END); } else { @@ -336,7 +336,7 @@ static void verify_update_service(VSTREAM *client_stream) dict_put(verify_map, STR(addr), STR(buf)); } attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, VRFY_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK, ATTR_TYPE_END); } } @@ -423,8 +423,8 @@ static void verify_query_service(VSTREAM *client_stream) * Respond to the client. */ attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, VRFY_STAT_OK, - ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, addr_status, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_OK, + ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status, ATTR_TYPE_STR, MAIL_ATTR_WHY, text, ATTR_TYPE_END); @@ -503,7 +503,7 @@ static void verify_service(VSTREAM *client_stream, char *unused_service, } else { msg_warn("unrecognized request: \"%s\", ignored", STR(request)); attr_print(client_stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, VRFY_STAT_BAD, + ATTR_TYPE_INT, MAIL_ATTR_STATUS, VRFY_STAT_BAD, ATTR_TYPE_END); } } diff --git a/postfix/src/virtual/virtual.c b/postfix/src/virtual/virtual.c index fd5df201d..0d636796e 100644 --- a/postfix/src/virtual/virtual.c +++ b/postfix/src/virtual/virtual.c @@ -174,8 +174,8 @@ /* Postfix is final destination for the specified list of domains; /* mail is delivered via the $virtual_transport mail delivery transport. /* .IP "\fBvirtual_transport (virtual)\fR" -/* The default mail delivery transport for domains that match the -/* $virtual_mailbox_domains parameter value. +/* The default mail delivery transport and next-hop destination for +/* final delivery to domains listed with $virtual_mailbox_domains. /* LOCKING CONTROLS /* .ad /* .fi @@ -432,6 +432,9 @@ static void post_init(char *unused_name, char **unused_argv) */ set_eugid(var_owner_uid, var_owner_gid); + /* + * No case folding needed: the recipient address is case folded. + */ virtual_mailbox_maps = maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps, DICT_FLAG_LOCK | DICT_FLAG_PARANOID); diff --git a/postfix/src/xsasl/Makefile.in b/postfix/src/xsasl/Makefile.in index 2a2d51c0b..ac9d8f3ac 100644 --- a/postfix/src/xsasl/Makefile.in +++ b/postfix/src/xsasl/Makefile.in @@ -104,6 +104,8 @@ xsasl_cyrus_log.o: xsasl_cyrus_common.h xsasl_cyrus_log.o: xsasl_cyrus_log.c xsasl_cyrus_security.o: ../../include/name_mask.h xsasl_cyrus_security.o: ../../include/sys_defs.h +xsasl_cyrus_security.o: ../../include/vbuf.h +xsasl_cyrus_security.o: ../../include/vstring.h xsasl_cyrus_security.o: xsasl_cyrus_common.h xsasl_cyrus_security.o: xsasl_cyrus_security.c xsasl_cyrus_server.o: ../../include/argv.h