]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20060123
authorWietse Venema <wietse@porcupine.org>
Mon, 23 Jan 2006 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:04 +0000 (06:32 +0000)
162 files changed:
postfix/HISTORY
postfix/README_FILES/CDB_README
postfix/README_FILES/OVERVIEW
postfix/README_FILES/SMTPD_POLICY_README
postfix/README_FILES/TLS_README
postfix/RELEASE_NOTES
postfix/html/CDB_README.html
postfix/html/OVERVIEW.html
postfix/html/SMTPD_POLICY_README.html
postfix/html/TLS_README.html
postfix/html/cleanup.8.html
postfix/html/flush.8.html
postfix/html/pickup.8.html
postfix/html/postalias.1.html
postfix/html/postconf.5.html
postfix/html/postdrop.1.html
postfix/html/postmap.1.html
postfix/html/postqueue.1.html
postfix/html/proxymap.8.html
postfix/html/qmqpd.8.html
postfix/html/scache.8.html
postfix/html/sendmail.1.html
postfix/html/smtpd.8.html
postfix/html/tlsmgr.8.html
postfix/html/trivial-rewrite.8.html
postfix/html/virtual.8.html
postfix/man/Makefile.in
postfix/man/man1/postalias.1
postfix/man/man1/postmap.1
postfix/man/man1/sendmail.1
postfix/man/man5/postconf.5
postfix/man/man8/cleanup.8
postfix/man/man8/virtual.8
postfix/mantools/dehtml [new file with mode: 0755]
postfix/mantools/postlink
postfix/proto/CDB_README.html
postfix/proto/SMTPD_POLICY_README.html
postfix/proto/TLS_README.html
postfix/proto/postconf.proto
postfix/src/anvil/anvil.c
postfix/src/bounce/bounce.c
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup_init.c
postfix/src/flush/flush.c
postfix/src/global/Makefile.in
postfix/src/global/abounce.c
postfix/src/global/anvil_clnt.c
postfix/src/global/bounce.c
postfix/src/global/defer.c
postfix/src/global/deliver_pass.c
postfix/src/global/deliver_request.c
postfix/src/global/dict_ldap.c
postfix/src/global/dict_mysql.c
postfix/src/global/dict_pgsql.c
postfix/src/global/dict_proxy.c
postfix/src/global/dsn_mask.c
postfix/src/global/ehlo_mask.ref
postfix/src/global/mail_addr_find.c
postfix/src/global/mail_addr_map.c
postfix/src/global/mail_command_client.c
postfix/src/global/mail_stream.c
postfix/src/global/mail_version.h
postfix/src/global/maps.c
postfix/src/global/post_mail.c
postfix/src/global/rcpt_buf.c
postfix/src/global/rcpt_print.c
postfix/src/global/resolve_clnt.c
postfix/src/global/rewrite_clnt.c
postfix/src/global/scache_clnt.c
postfix/src/global/trace.c
postfix/src/global/verify_clnt.c
postfix/src/global/virtual8.in [deleted file]
postfix/src/global/virtual8.ref [deleted file]
postfix/src/global/virtual8_map [deleted file]
postfix/src/global/virtual8_maps.c [deleted file]
postfix/src/global/virtual8_maps.h [deleted file]
postfix/src/local/forward.c
postfix/src/local/local.c
postfix/src/local/mailbox.c
postfix/src/local/unknown.c
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/pickup/pickup.c
postfix/src/postalias/postalias.c
postfix/src/postdrop/postdrop.c
postfix/src/postmap/postmap.c
postfix/src/postqueue/Makefile.in
postfix/src/postqueue/postqueue.c
postfix/src/proxymap/proxymap.c
postfix/src/qmgr/qmgr_deliver.c
postfix/src/qmqpd/qmqpd.c
postfix/src/scache/scache.c
postfix/src/sendmail/sendmail.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/legacy.c [new file with mode: 0644]
postfix/src/smtp/levels.c [new file with mode: 0644]
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_addr.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_map11.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_sasl_glue.c
postfix/src/smtp/smtp_session.c
postfix/src/smtp/tls_policy.in [new file with mode: 0644]
postfix/src/smtp/tls_policy.ref [new file with mode: 0644]
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_check.ref
postfix/src/smtpd/smtpd_check.ref2
postfix/src/smtpd/smtpd_check_dsn.ref
postfix/src/smtpd/smtpd_dsn_fix.c
postfix/src/smtpd/smtpd_dsn_fix.h
postfix/src/spawn/Makefile.in
postfix/src/tls/tls_mgr.c
postfix/src/tls/tls_verify.c
postfix/src/tlsmgr/tlsmgr.c
postfix/src/trivial-rewrite/resolve.c
postfix/src/trivial-rewrite/rewrite.c
postfix/src/trivial-rewrite/transport.c
postfix/src/trivial-rewrite/trivial-rewrite.c
postfix/src/util/Makefile.in
postfix/src/util/attr.h
postfix/src/util/attr_clnt.c
postfix/src/util/attr_print0.c
postfix/src/util/attr_print64.c
postfix/src/util/attr_print_plain.c
postfix/src/util/attr_scan0.c
postfix/src/util/attr_scan64.c
postfix/src/util/attr_scan_plain.c
postfix/src/util/auto_clnt.c
postfix/src/util/auto_clnt.h
postfix/src/util/dict.c
postfix/src/util/dict.h
postfix/src/util/dict_alloc.c
postfix/src/util/dict_cdb.c
postfix/src/util/dict_db.c
postfix/src/util/dict_dbm.c
postfix/src/util/dict_env.c
postfix/src/util/dict_ni.c
postfix/src/util/dict_nis.c
postfix/src/util/dict_nisplus.c
postfix/src/util/dict_open.c
postfix/src/util/dict_pcre.c
postfix/src/util/dict_regexp.c
postfix/src/util/dict_sdbm.c
postfix/src/util/dict_tcp.c
postfix/src/util/dict_unix.c
postfix/src/util/htable.c
postfix/src/util/match_list.c
postfix/src/util/match_ops.c
postfix/src/util/myaddrinfo.ref
postfix/src/util/name_mask.c
postfix/src/util/name_mask.h
postfix/src/util/unescape.c
postfix/src/verify/verify.c
postfix/src/virtual/virtual.c
postfix/src/xsasl/Makefile.in

index 8a4f3200f3f1e0ca7c91bd7fe84019946c672895..7d3de16e4afa154d5fcda5c63150590f41bc4e55 100644 (file)
@@ -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.
 
index 8c32ee4dd8b1a9a9e312d2b1463d93d314f1754a..0d00bf59ac8519d4dd076889ab5b930eab8272d3 100644 (file)
@@ -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
index c9d40269f3cb44fb27dc6083d4b08e1c3995edd5..1d9ae180f5118dbbdfefb2145f7b41a607c9f67e 100644 (file)
@@ -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
index ecaa5151a4fa59307f9e0d41455ae25b53c87572..e58508cdddfb4b9e328a6457e01bbe2bf855aad4 100644 (file)
@@ -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.
index 676b4005ad8a5bac6728d1077793604506f53835..e30f9fbbef3b5c31f694edeb0934cf3a1cac272a 100644 (file)
@@ -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.
 
+N\bNO\bOT\bTE\bE:\b: D\bDo\bo n\bno\bot\bt u\bus\bse\be G\bGn\bnu\bu T\bTL\bLS\bS.\b. I\bIt\bt w\bwi\bil\bll\bl s\bsp\bpo\bon\bnt\bta\ban\bne\beo\bou\bus\bsl\bly\by t\bte\ber\brm\bmi\bin\bna\bat\bte\be a\ba p\bpr\bro\boc\bce\bes\bss\bs w\bwi\bit\bth\bh e\bex\bxi\bit\bt
+s\bst\bta\bat\btu\bus\bs c\bco\bod\bde\be 2\b2,\b, i\bin\bns\bst\bte\bea\bad\bd o\bof\bf p\bpr\bro\bop\bpe\ber\brl\bly\by r\bre\bep\bpo\bor\brt\bti\bin\bng\bg p\bpr\bro\bob\bbl\ble\bem\bms\bs t\bto\bo P\bPo\bos\bst\btf\bfi\bix\bx,\b, s\bso\bo t\bth\bha\bat\bt i\bit\bt
+c\bca\ban\bn l\blo\bog\bg t\bth\bhe\bem\bm t\bto\bo t\bth\bhe\be m\bma\bai\bil\bll\blo\bog\bg f\bfi\bil\ble\be.\b.
+
   * 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
 
+R\bRe\beq\bqu\bui\bir\bri\bin\bng\bg T\bTL\bLS\bS e\ben\bnc\bcr\bry\byp\bpt\bti\bio\bon\bn
+
 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
+
+D\bDi\bis\bsa\bab\bbl\bli\bin\bng\bg s\bse\ber\brv\bve\ber\br c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be v\bve\ber\bri\bif\bfi\bic\bca\bat\bti\bio\bon\bn
 
 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
-
-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.
-
-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.
-
-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.
-
-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:
+        smtp_enforce_tls = yes
+        smtp_tls_enforce_peername = no
+
+P\bPe\ber\br-\b-s\bsi\bit\bte\be T\bTL\bLS\bS p\bpo\bol\bli\bic\bci\bie\bes\bs
+
+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 smtp_tls_per_site table is searched for a policy that matches the following
+information:
+
+    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 M\bMA\bAY\bY 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 N\bNO\bON\bNE\bE) 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 N\bNO\bON\bNE\bE or a less specific M\bMA\bAY\bY 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 N\bNO\bON\bNE\bE and M\bMU\bUS\bST\bT_\b_N\bNO\bOP\bPE\bEE\bER\bRM\bMA\bAT\bTC\bCH\bH or a less
+        specific M\bMA\bAY\bY 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:
+
+  * 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".
+
+  * 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 M\bMA\bAY\bY 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.
+
+C\bCl\blo\bos\bsi\bin\bng\bg a\ba D\bDN\bNS\bS l\blo\boo\bop\bph\bho\bol\ble\be w\bwi\bit\bth\bh  p\bpe\ber\br-\b-s\bsi\bit\bte\be T\bTL\bLS\bS p\bpo\bol\bli\bic\bci\bie\bes\bs
+
+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 M\bMU\bUS\bST\bT 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.
 
-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:
+Example:
 
-  * If no match was found, the policy is applied as specified with
-    smtp_enforce_tls.
+    /etc/postfix/main.cf:
+        smtp_tls_per_site = hash:/etc/postfix/tls_per_site
+        relayhost = [msa.example.net]:587
 
-  * 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.
+    /etc/postfix/tls_per_site:
+        # relayhost exact nexthop match
+        [msa.example.net]:587       MUST
 
-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.
+        # example.org (as nexthop) has MX hosts with broken TLS.
+        example.org                 NONE
 
-Example:
+        # Except for (as host) mx1.example.org which works.
+        mx1.example.org             MAY
 
-    /etc/postfix/main.cf:
-        smtp_tls_per_site = hash:/etc/postfix/tls_per_site
+D\bDi\bis\bsc\bco\bov\bve\ber\bri\bin\bng\bg s\bse\ber\brv\bve\ber\brs\bs t\bth\bha\bat\bt s\bsu\bup\bpp\bpo\bor\brt\bt T\bTL\bLS\bS
 
 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
 
-S\bSe\ber\brv\bve\ber\br c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be v\bve\ber\bri\bif\bfi\bic\bca\bat\bti\bio\bon\bn
+S\bSe\ber\brv\bve\ber\br c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be v\bve\ber\bri\bif\bfi\bic\bca\bat\bti\bio\bon\bn d\bde\bep\bpt\bth\bh
 
 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
     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.
+
 C\bCr\bre\bed\bdi\bit\bts\bs
 
   * 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.
 
index 96233b96b7b6b3a88fec7ebbb5a407b12f7452ef..4dde0c609cbf6632cca0eb20fddd992cd15af451 100644 (file)
@@ -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
index 4307cc6f756ae8ec232c44c5b1ebe34088fb9cb7..9d81ee2f7a5f960f9dd7aa0cd9cc14a5b92d59de 100644 (file)
@@ -54,7 +54,7 @@ available from <a href="http://www.corpit.ru/mjt/tinycdb.html">http://www.corpit
 <p>  Tinycdb is preferred, since it is a bit faster, has additional
 useful functionality and is much simpler to use. </p>
 
-<p>To build Postfix after you have installed CDB, use something
+<p>To build Postfix after you have installed tinycdb, use something
 like: </p>
 
 <blockquote>
@@ -65,7 +65,11 @@ like: </p>
     "AUXLIBS=$CDB/libcdb.a"
 % make
 </pre>
-for tinycdb, or alternatively, for the D.J.B. version:<br>
+</blockquote>
+
+<p> Alternatively, for the D.J.B. version of CDB:<p>
+
+<blockquote>
 <pre>
 % make tidy
 % CDB=../../../cdb-0.75
index 84cbd7f21bd272b860e2dc7f2bb5cd131ba4f11e..9bdf973e62da0a23576f546b4cd3ee06249f0e1c 100644 (file)
@@ -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 <a href="master.8.html">master(8)</a> server is also responsible
 for enforcing the server process count limits as specified in the
-<b>master.cf</b> configuration file. The picture below gives the
+<a href="master.5.html"><b>master.cf</b></a> configuration file. The picture below gives the
 program hierarchy when Postfix is started up. Only some of the mail
 handling daemon processes are shown. </p>
 
@@ -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. </p>
 
-<li> <p> The <a href="postconf.1.html">postconf(1)</a> command displays or updates Postfix main.cf
+<li> <p> The <a href="postconf.1.html">postconf(1)</a> command displays or updates Postfix <a href="postconf.5.html">main.cf</a>
 parameters and displays system dependent information about the
 supported file locking methods, and the supported types of lookup
 tables.  </p>
index 869861c9bb7f928dbf30e86341edf645b73db151..179b22fc20ee896ccf4ad9ce5d8adfcc6e0bd0ec 100644 (file)
@@ -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
     </p>
 
     <li> <p> When an attribute value is unavailable, the client
-    either does not send the attribute, or sends the attribute with
-    an empty value ("name="). </p>
+    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. </p>
+
+    <li> <p> 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.
+    </p>
+
+    <li> <p> 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.  </p>
 
     <li> <p> 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: </p>
 
 <blockquote>
 <pre>
- 1 /etc/postfix/master.cf:
+ 1 /etc/postfix/<a href="master.5.html">master.cf</a>:
  2     policy  unix  -       n       n       -       -       spawn
  3       user=nobody argv=/some/where/policy-server
  4 
- 5 /etc/postfix/main.cf:
+ 5 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
  6     <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
  7         ... 
  8         <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> 
@@ -239,8 +251,8 @@ daemon, you would use something like this: </p>
 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")
+<a href="postconf.5.html">main.cf</a> with an explicit "policy_time_limit" setting.  The name of
+the parameter is the name of the <a href="master.5.html">master.cf</a> entry ("policy")
 concatenated with the "_time_limit" suffix.  </p>
 
 <li> <p> Lines 8, 9: always specify "<a href="postconf.5.html#check_policy_service">check_policy_service</a>" AFTER
@@ -254,11 +266,11 @@ TCP sockets instead: </p>
 
 <blockquote>
 <pre>
- 1 /etc/postfix/master.cf:
+ 1 /etc/postfix/<a href="master.5.html">master.cf</a>:
  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/<a href="postconf.5.html">main.cf</a>:
  6     <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
  7         ... 
  8         <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> 
@@ -320,7 +332,7 @@ $greylist_delay=60;
 
 <p> 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. </p>
+in <a href="master.5.html">master.cf</a> for the policy service. </p>
 
 <p> Example: </p>
 
@@ -346,11 +358,11 @@ processes only: </p>
 
 <blockquote>
 <pre>
-1 /etc/postfix/master.cf:
+1 /etc/postfix/<a href="master.5.html">master.cf</a>:
 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/<a href="postconf.5.html">main.cf</a>:
 6      policy_time_limit = 3600
 </pre>
 </blockquote>
@@ -366,8 +378,8 @@ each request and reply. </p>
 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")
+<a href="postconf.5.html">main.cf</a> with an explicit "policy_time_limit" setting.  The name of
+the parameter is the name of the <a href="master.5.html">master.cf</a> entry ("policy")
 concatenated with the "_time_limit" suffix.  </p>
 
 </ul>
@@ -378,11 +390,11 @@ client/server configuration</a>" section above.  </p>
 
 <blockquote>
 <pre>
-1 /etc/postfix/master.cf:
+1 /etc/postfix/<a href="master.5.html">master.cf</a>:
 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/<a href="postconf.5.html">main.cf</a>:
 6      127.0.0.1:9998_time_limit = 3600
 </pre>
 </blockquote>
@@ -400,7 +412,7 @@ forged MAIL FROM domains could be found at
 
 <blockquote>
 <pre>
- 1 /etc/postfix/main.cf:
+ 1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
  2     <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
  3         <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a>
  4         ...
@@ -450,7 +462,7 @@ database relatively quickly. </p>
 
 <blockquote>
 <pre>
- 1 /etc/postfix/main.cf:
+ 1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
  2     <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
  3         <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a>
  4         ...
index 0ff0d03f25fc4633636d5e36171a17c0cce4e3e3..29d77edff771689594503e9d581fba640b556f14 100644 (file)
@@ -129,6 +129,11 @@ the <tt>make(1)</tt> files with the necessary definitions. This is
 done by invoking the command "<tt>make makefiles</tt>" in the Postfix
 top-level directory and with arguments as shown next. </p>
 
+<p> <b> 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.
+</b> </p>
+
 <ul>
 
 <li> <p> If the OpenSSL include files (such as <tt>ssl.h</tt>) are
@@ -274,7 +279,7 @@ is correctly configured to supply its intermediate CA certificate). </p>
 
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = /etc/postfix/server.pem
     <a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> = $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>
 </pre>
@@ -284,7 +289,7 @@ is correctly configured to supply its intermediate CA certificate). </p>
 
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> = /etc/postfix/server-dsa.pem
     <a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> = $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>
 </pre>  
@@ -334,7 +339,7 @@ the TLS handshake when client certificates are requested. </p>
 <p> Example: </p>
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> = /etc/postfix/CAcert.pem
     <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> = /etc/postfix/certs
 </pre>
@@ -376,7 +381,7 @@ strongly discouraged. </p>
 
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> = 0
 </pre>
 </blockquote>
@@ -392,7 +397,7 @@ since the headers may be changed by intermediate servers. </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> = yes
 </pre>
 </blockquote>
@@ -407,7 +412,7 @@ using "<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> = yes". </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> = yes
 </pre>
 </blockquote>
@@ -430,7 +435,7 @@ This option is off by default and should only seldom be used. </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> = yes
 </pre>
 </blockquote>
@@ -442,8 +447,8 @@ Outlook [Express] prefer the "wrapper" mode.  This is true for OE
 (Win32 &lt; 5.0 and Win32 &gt;=5.0 when run on a port&lt;&gt;25
 and OE (5.01 Mac on all ports). </p>
 
-<p> 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
+<p> It is strictly discouraged to use this mode from <a href="postconf.5.html">main.cf</a>. If
+you want to support this service, enable a special port in <a href="master.5.html">master.cf</a>
 and specify "-o <a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a> = yes" as an <a href="smtpd.8.html">smtpd(8)</a> command
 line option.  Port 465 (smtps) was once chosen for this feature.
 </p>
@@ -452,7 +457,7 @@ line option.  Port 465 (smtps) was once chosen for this feature.
  
 <blockquote>
 <pre>
-/etc/postfix/master.cf:
+/etc/postfix/<a href="master.5.html">master.cf</a>:
     smtps    inet  n       -       n       -       -       smtpd
       -o <a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a>=yes -o <a href="postconf.5.html#smtpd_sasl_auth_enable">smtpd_sasl_auth_enable</a>=yes
 </pre>
@@ -477,7 +482,7 @@ feature.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = no
 </pre>
 </blockquote>
@@ -500,7 +505,7 @@ logged. </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a> = no
 </pre>
 </blockquote>
@@ -515,7 +520,7 @@ CA issues special CA which then issues the actual certificate...)
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a> = 5
 </pre>
 </blockquote>
@@ -536,7 +541,7 @@ set "<a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> = yes
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> = no
 </pre>
 </blockquote>
@@ -560,7 +565,7 @@ the cost of repeatedly negotiating TLS session keys is high.</p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = btree:/etc/postfix/smtpd_scache
 </pre>
 </blockquote>
@@ -574,7 +579,7 @@ recommends a maximum of 24 hours.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> = 3600s
 </pre>
 </blockquote>
@@ -622,7 +627,7 @@ certificate must no longer be used (e.g. an employee leaving). </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> = 
         ... 
         <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a> 
@@ -643,7 +648,7 @@ the user or host.</p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a> = 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
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> = DEFAULT
 </pre>
 </blockquote>
@@ -691,7 +696,7 @@ those distributed with other TLS packages. </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = /etc/postfix/dh_1024.pem
     <a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> = /etc/postfix/dh_512.pem
 </pre>
@@ -707,7 +712,7 @@ handshake procedures.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> = 300s
 </pre>
 </blockquote>
@@ -726,9 +731,23 @@ key configuration </a>
 
 <li><a href="#client_tls_cache">Client-side TLS session cache</a>
 
-<li><a href="#client_tls"> Enabling TLS in the Postfix SMTP client </a>
+<li><a href="#client_tls_enable"> Enabling TLS in the Postfix SMTP client </a>
+
+<li><a href="#client_tls_require"> Requiring TLS encryption </a>
+
+<li><a href="#client_tls_nopeer"> Disabling server certificate verification </a>
+
+<li><a href="#client_tls_per_site"> Per-site TLS policies </a>
+
+<!--
+<li><a href="#client_tls_obs"> Obsolete per-site TLS policy support </a>
+-->
+
+<li><a href="#client_tls_harden"> Closing a DNS loophole with <!-- legacy --> per-site TLS policies </a>
+
+<li><a href="#client_tls_discover"> Discovering servers that support TLS </a>
 
-<li><a href="#client_vrfy_server">Server certificate verification</a>
+<li><a href="#client_vrfy_server">Server certificate verification depth</a>
 
 <li> <a href="#client_cipher">Client-side cipher controls </a>
 
@@ -788,7 +807,7 @@ the overhead of the TLS exchange. </p>
 certificates issued by these CAs, append the root certificate to
 $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> or install it in the $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> 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 $<a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a>
 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). </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = /etc/postfix/client.pem
     <a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> = $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>
 </pre>
@@ -810,7 +829,7 @@ is correctly configured to supply its intermediate CA certificate). </p>
 
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> = /etc/postfix/client-dsa.pem
     <a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> = $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>
 </pre>  
@@ -849,7 +868,7 @@ when the certificate is needed.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> = /etc/postfix/CAcert.pem
     <a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> = /etc/postfix/certs
 </pre>
@@ -888,7 +907,7 @@ transmission after STARTTLS </td> </tr>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> = 0
 </pre>
 </blockquote>
@@ -915,7 +934,7 @@ is allowed to negotiate per unit time.</p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = btree:/etc/postfix/smtp_scache
 </pre>
 </blockquote>
@@ -929,39 +948,37 @@ recommends a maximum of 24 hours.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a> = 3600s
 </pre>
 </blockquote>
 
-<h3><a name="client_tls"> Enabling TLS in the Postfix SMTP client </a>
-</h3>
+<h3><a name="client_tls_enable"> Enabling TLS in the Postfix SMTP
+client </a> </h3>
 
 <p> 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. </p>
 
-<p> 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 <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
-recipient/site specific options that are described below. </p>
-
-<p> 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.  </p>
+<p> 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. </p>
 
 <p> Example: </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> = yes
 </pre>
 </blockquote>
 
+<h3><a name="client_tls_require"> Requiring TLS encryption </a>
+</h3>
+
 <p> 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.  </p>
 
-<p> 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
+<p> 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
 <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> option which is discussed below. </p>
 
-<p> This option is useful only if you know that you will only
+<p> Enforcing the use of TLS is useful if you know that you will
+only
 connect to servers that support <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> _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.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
-    <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = no
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+    <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes
 </pre>
 </blockquote>
 
+<h3> <a name="client_tls_nopeer"> Disabling server certificate
+verification </a> </h3>
+
 <p> As of <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> the requirements for hostname checking for MTA
 clients are not set. When TLS is required (<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes),
 the option <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> 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. </p>
 
-<p> Note: the <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> setting has no effect on
-sessions that are controlled via the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table.  </p>
-
-<p>  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). </p>
+<p>  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
+<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes, you should probably also set
+<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = 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.
+</p>
 
 <p> Example: </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
-    <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = yes
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+    <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes
+    <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = no
 </pre>
 </blockquote>
 
-<p> 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. </p>
-
-<p> 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 <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table, appropriate action
-is taken.  </p>
-
-<p> 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 <a href="transport.5.html">transport(5)</a> table or by the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting.
-In these cases the <a href="postconf.5.html#relayhost">relayhost</a> etc. must be listed in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
-table, instead of the recipient domain name. </p>
-
-<p> 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:  </p>
+<h3> <a name="client_tls_per_site"> Per-site TLS policies </a> </h3>
+
+<p> 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. </p>
+
+<!-- insert new-style TLS policy mechanism here
+
+<h3> <a name="client_tls_obs"> Obsolete per-site TLS policy support 
+</a> </h3>
+
+<p> This section describes an obsolete per-site TLS policy mechanism.
+Unlike the newer mechanism it supports TLS policy lookup by server
+hostname, and lacks control over what names can appear in server
+certificates.  Because of this, the obsolete mechanism is vulnerable
+to false DNS hostname information in MX or CNAME records.  These
+attacks can be eliminated only with great difficulty.  </p>
+
+-->
+
+<p> The <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table is searched for a policy that matches
+the following information:  </p>
 
 <blockquote>
 
 <dl>
 
-<dt> NONE </dt> <dd> Don't use TLS at all. </dd>
+<dt> remote SMTP server hostname </dt> <dd> 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. </dd>
+
+<dt> next-hop destination </dt> <dd> This is normally the domain
+portion of the recipient address, but it may be overruled by
+information from the <a href="transport.5.html">transport(5)</a> table, from the <a href="postconf.5.html#relayhost">relayhost</a> parameter
+setting, or from the <a href="postconf.5.html#relay_transport">relay_transport</a> setting. When it's not the
+recipient domain, the next-hop destination can have the Postfix-specific
+form "<tt>[name]</tt>", <tt>[name]:port</tt>", "<tt>name</tt>" or
+"<tt>name:port</tt>".  </dd>
+
+</dl>
+
+</blockquote>
+
+<p> 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.  </p>
+
+<p> The <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table uses a simple "<i>name whitespace
+value</i>" 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:  </p>
 
-<dt> MAY </dt> <dd> Try to use STARTTLS if offered, otherwise use
-the unencrypted connection. </dd>
+<blockquote>
 
-<dt> MUST </dt> <dd> 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. </dd>
+<dl>
 
-<dt> MUST_NOPEERMATCH </dt> <dd> 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. </dd>
+<dt> NONE </dt> <dd> Don't use TLS at all. This overrides a less
+specific <b>MAY</b> lookup result from the alternate host or next-hop
+lookup key, and overrides the global <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>, <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>,
+and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> settings. </dd>
+
+<dt> MAY </dt> <dd> Try to use TLS if the server announces support,
+otherwise use the unencrypted connection. This has less precedence
+than a more specific result (including <b>NONE</b>) from the alternate
+host or next-hop lookup key, and has less precedence than the more
+specific global "<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes" or "<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
+= yes".  </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd> 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 <b>NONE</b>
+or a less specific <b>MAY</b> lookup result from the alternate host
+or next-hop lookup key, and overrides the global <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>,
+<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> settings.  </dd>
+
+<dt> MUST </dt> <dd> 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 <b>NONE</b>
+and <b>MUST_NOPEERMATCH</b> or a less specific <b>MAY</b> lookup
+result from the alternate host or next-hop lookup key, and overrides
+the global <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>, <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
+settings.  </dd>
 
 </dl>
 
 </blockquote>
 
-<p> The actual TLS usage policy depends not only on whether the
-next-hop destination or remote SMTP server hostname are found in
-the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table, but also on the <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>
-setting:  </p>
+<p> The precedences between global (<a href="postconf.5.html">main.cf</a>) and per-site TLS
+policies can be summarized as follows: </p>
 
 <ul>
 
-<li> <p> If no match was found, the policy is applied as specified
-with <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>. </p>
+<li> <p> When neither the remote SMTP server hostname nor the
+next-hop destination are found in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table, the
+policy is based on <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>, <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> and
+<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>. Note: "<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes" and
+"<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = yes" imply "<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> = yes". </p>
 
-<li> <p> If a match was found, and the <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> policy is
-"enforce", NONE explicitly switches it off; otherwise the "enforce"
-mode is used even for entries that specify MAY. </p>
+<li> <p> 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).  </p>
+
+<li> <p> After the per-site policy lookups are combined, the result
+generally overrides the global policy. The exception is the less
+specific <b>MAY</b> per-site policy, which is overruled by the more
+specific global "<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes" with server certificate
+verification as specified with the <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
+parameter.  </p>
 
 </ul>
 
-<p> 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
-<a href="transport.5.html">transport(5)</a> table entries for sensitive domains with explicit
-<a href="smtp.8.html">smtp</a>:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table. </p>
+<h3> <a name="client_tls_harden"> Closing a DNS loophole with 
+<!-- legacy --> per-site TLS policies </a> </h3>
+
+<p> 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: </p>
+
+<ul>
+
+<li> <p> Eliminate MX lookups. Specify local <a href="transport.5.html">transport(5)</a> table
+entries for sensitive domains with explicit <a href="smtp.8.html">smtp</a>:[<i>mailhost</i>]
+or <a href="smtp.8.html">smtp</a>:[<i>mailhost</i>]:<i>port</i> destinations (you can assure
+security of this table unlike DNS); in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table
+specify the value <b>MUST</b> for the key [<i>mailhost</i>] or
+<a href="smtp.8.html">smtp</a>:[<i>mailhost</i>]:<i>port</i>. 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. </p>
+
+<li> <p> Disallow CNAME hostname overrides. In <a href="postconf.5.html">main.cf</a> specify
+"<a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> = 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.  </p>
+
+</ul>
 
 <p> Example: </p>
-<blockquote>
-<pre>
-/etc/postfix/main.cf:
+
+<blockquote> <pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> = hash:/etc/postfix/tls_per_site
+    <a href="postconf.5.html#relayhost">relayhost</a> = [msa.example.net]:587
+
+/etc/postfix/tls_per_site:
+    # <a href="postconf.5.html#relayhost">relayhost</a> 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
 </pre>
 </blockquote>
 
+<h3> <a name="client_tls_discover"> Discovering servers that support
+TLS </a> </h3>
+
 <p> 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. </p>
@@ -1118,12 +1230,12 @@ postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_note_starttls_offer">smtp_tls_note_starttls_offer</a> = yes
 </pre>
 </blockquote>
 
-<h3><a name="client_vrfy_server">Server certificate verification</a> </h3>
+<h3><a name="client_vrfy_server">Server certificate verification depth</a> </h3>
 
 <p> 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...) </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a> = 5
 </pre>
 </blockquote>
@@ -1154,7 +1266,7 @@ don't know what to do with it, simply don't touch it and leave the
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_tls_cipherlist">smtp_tls_cipherlist</a> = DEFAULT
 </pre>
 </blockquote>
@@ -1171,7 +1283,7 @@ defers delivery if no alternative server is available. </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#smtp_starttls_timeout">smtp_starttls_timeout</a> = 300s
 </pre>
 </blockquote>
@@ -1191,7 +1303,7 @@ session key.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> = 32
 </pre>
 </blockquote>
@@ -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.  </p>
 
-<p> Examples (specify only one in main.cf): </p>
+<p> Examples (specify only one in <a href="postconf.5.html">main.cf</a>): </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#tls_random_source">tls_random_source</a> = dev:/dev/urandom
     <a href="postconf.5.html#tls_random_source">tls_random_source</a> = egd:/var/run/egd-pool
 </pre>
@@ -1227,7 +1339,7 @@ entropy source, a larger amount of data can be read.  </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#tls_random_bytes">tls_random_bytes</a> = 32
 </pre>
 </blockquote>
@@ -1242,7 +1354,7 @@ The default maximal time interval is 1 hour. </p>
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#tls_random_reseed_period">tls_random_reseed_period</a> = 3600s
 </pre>
 </blockquote>
@@ -1260,7 +1372,7 @@ the file location should probably be on the /var partition (but
  
 <blockquote>
 <pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#tls_random_exchange_name">tls_random_exchange_name</a> = /etc/postfix/prng_exch
     <a href="postconf.5.html#tls_random_prng_update_period">tls_random_prng_update_period</a> = 3600s
 </pre>
@@ -1380,7 +1492,7 @@ super-user privileges. </p>
 </blockquote>
 
 <li> <p> Configure Postfix, by adding the following to
-<tt>/etc/postfix/main.cf</tt>. </p>
+<tt>/etc/postfix/<a href="postconf.5.html">main.cf</a> </tt>. </p>
 
 <blockquote>
 <pre>
@@ -1424,7 +1536,7 @@ patch by Lutz J&auml;nicke, but differs in a few minor ways. </p>
 
 <ul>
 
-<li> <p> main.cf: Specify "btree" instead of "sdbm" for TLS
+<li> <p> <a href="postconf.5.html">main.cf</a>: Specify "btree" instead of "sdbm" for TLS
 session cache databases. </p>
 
 <p> TLS session cache databases are now accessed only by the
@@ -1439,7 +1551,7 @@ In most cases, btree databases should be adequate.  </p>
 <p> NOTE:  You cannot use dbm databases. TLS session objects
 are too large. </p>
 
-<li> <p> master.cf: Specify "unix" instead of "fifo" as
+<li> <p> <a href="master.5.html">master.cf</a>: Specify "unix" instead of "fifo" as
 the tlsmgr service type. </p>
 
 <p> The <a href="smtp.8.html">smtp(8)</a> and <a href="smtpd.8.html">smtpd(8)</a> processes now use a client-server
@@ -1447,8 +1559,22 @@ protocol in order to access the <a href="tlsmgr.8.html">tlsmgr(8)</a> pseudo-ran
 generation (PRNG) pool, and in order to access the TLS session
 cache databases. Such a protocol cannot be run across fifos. </p>
 
+<li> <p> <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>: the MUST_NOPEERMATCH per-site policy
+cannot override the global "<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = yes" setting.
+</p>
+
+<li> <p> <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>: a combined (NONE + MAY) lookup result
+for (hostname and next-hop destination) produces counter-intuitive
+results for different <a href="postconf.5.html">main.cf</a> settings.  TLS is enabled with
+"<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = no", but it is disabled when both
+"<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes" and "<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = yes".
+</p>
+
 </ul>
 
+<p> The <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> limitations were removed by the end of
+the Postfix 2.2 support cycle. </p>
+
 <h2><a name="credits">Credits </a> </h2>
 
 <ul>
@@ -1459,6 +1585,10 @@ J&auml;nicke at Cottbus Technical University.
 <li> Wietse Venema adopted the code, did some restructuring, and
 compiled this part of the documentation from Lutz's documents.
 
+<li> Victor Duchovni was instrumental with the re-implementation
+of the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> code in terms of enforcement levels, which
+simplified the implementation greatly.
+
 </ul>
 
 </body>
index a5f60db287c5df9fba230301b5f0749307cda67b..6d744f593d500679e6eb318a225ce39b2aa73c1e 100644 (file)
@@ -69,7 +69,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        <b>then else</b> and other logical relationships.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes   to  <b>main.cf</b>  are  picked  up  automatically,  as
+       Changes   to  <a href="postconf.5.html"><b>main.cf</b></a>  are  picked  up  automatically,  as
        <a href="cleanup.8.html"><b>cleanup</b>(8)</a> processes run for  only  a  limited  amount  of
        time.  Use  the  command  "<b>postfix  reload</b>"  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).
 
 <b>BUILT-IN CONTENT FILTERING CONTROLS</b>
-       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.
 
        <b><a href="postconf.5.html#body_checks">body_checks</a> (empty)</b>
-              Optional lookup tables for  content  inspection  as
+              Optional  lookup  tables  for content inspection as
               specified in the <b><a href="postconf.5.html#body_checks">body_checks</a></b>(5) manual page.
 
        <b><a href="postconf.5.html#header_checks">header_checks</a> (empty)</b>
-              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 <b><a href="postconf.5.html#header_checks">header_checks</a></b>(5) manual page.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#body_checks_size_limit">body_checks_size_limit</a> (51200)</b>
               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 <a href="postconf.5.html#body_checks">body_checks</a> inspection.
 
        <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
-              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
               <b><a href="postconf.5.html#header_checks">header_checks</a></b>(5) manual page.
 
        <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
-              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 <b><a href="postconf.5.html#header_checks">header_checks</a></b>(5) manual page.
 
        Available in Postfix version 2.3 and later:
 
        <b><a href="postconf.5.html#message_reject_characters">message_reject_characters</a> (empty)</b>
-              The  set  of characters that Postfix will reject in
+              The set of characters that Postfix will  reject  in
               message content.
 
        <b><a href="postconf.5.html#message_strip_characters">message_strip_characters</a> (empty)</b>
@@ -150,19 +151,19 @@ CLEANUP(8)                                                          CLEANUP(8)
               will handle.
 
        <b><a href="postconf.5.html#strict_8bitmime">strict_8bitmime</a> (no)</b>
-              Enable  both  <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a>  and strict_8bit-
+              Enable both  <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a>  and  strict_8bit-
               mime_body.
 
        <b><a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a> (no)</b>
               Reject mail with 8-bit text in message headers.
 
        <b><a href="postconf.5.html#strict_8bitmime_body">strict_8bitmime_body</a> (no)</b>
-              Reject 8-bit message body text without  8-bit  MIME
+              Reject  8-bit  message body text without 8-bit MIME
               content encoding information.
 
        <b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b>
               Reject mail with invalid Content-Transfer-Encoding:
-              information for the message/* or  multipart/*  MIME
+              information  for  the message/* or multipart/* MIME
               content types.
 
 <b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
@@ -170,31 +171,31 @@ CLEANUP(8)                                                          CLEANUP(8)
        mail enters the mail system:
 
        <b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b>
-              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:
 
        <b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b>
-              Optional BCC  (blind  carbon-copy)  address  lookup
+              Optional  BCC  (blind  carbon-copy)  address lookup
               tables, indexed by sender address.
 
        <b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
-              Optional  BCC  (blind  carbon-copy)  address lookup
+              Optional BCC  (blind  carbon-copy)  address  lookup
               tables, indexed by recipient address.
 
 <b>ADDRESS TRANSFORMATION CONTROLS</b>
-       Address rewriting is delegated to  the  <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
-       daemon.   The  <a href="cleanup.8.html"><b>cleanup</b>(8)</a>  server  implements table driven
+       Address  rewriting  is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
+       daemon.  The <a href="cleanup.8.html"><b>cleanup</b>(8)</a>  server  implements  table  driven
        address mapping.
 
        <b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
-              The  recipient  of  mail  addressed  to  the   null
+              The   recipient  of  mail  addressed  to  the  null
               address.
 
        <b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
-              Optional  address mapping lookup tables for message
+              Optional address mapping lookup tables for  message
               headers and envelopes.
 
        <b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
@@ -205,49 +206,49 @@ CLEANUP(8)                                                          CLEANUP(8)
               Optional address mapping lookup tables for envelope
               and header sender addresses.
 
-       <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a>    (envelope_sender,     header_sender,</b>
+       <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a>     (envelope_sender,    header_sender,</b>
        <b>header_recipient)</b>
               What addresses are subject to address masquerading.
 
        <b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
-              Optional  list of domains whose subdomain structure
+              Optional list of domains whose subdomain  structure
               will be stripped off in email addresses.
 
        <b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
-              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 $<a href="postconf.5.html#masquerade_domains">masquerade_domains</a>.
 
        <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
-              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:
 
        <b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
               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:
 
        <b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
-              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:
 
-       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>   (envelope_sender,  envelope_recipient,</b>
+       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>  (envelope_sender,   envelope_recipient,</b>
        <b>header_sender, header_recipient)</b>
-              What   addresses   are  subject  to  <a href="postconf.5.html#canonical_maps">canonical_maps</a>
+              What  addresses  are  subject   to   <a href="postconf.5.html#canonical_maps">canonical_maps</a>
               address mapping.
 
        <b><a href="postconf.5.html#recipient_canonical_classes">recipient_canonical_classes</a>           (envelope_recipient,</b>
        <b>header_recipient)</b>
-              What addresses  are  subject  to  <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
+              What  addresses  are  subject  to <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
               <a href="postconf.5.html#recipient_canonical_maps">cal_maps</a> address mapping.
 
        <b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b>
@@ -255,15 +256,15 @@ CLEANUP(8)                                                          CLEANUP(8)
               address mapping.
 
        <b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
-              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.
 
 <b>RESOURCE AND RATE CONTROLS</b>
        <b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
-              The  maximal  number of addresses remembered by the
-              address duplicate filter  for  <a href="aliases.5.html"><b>aliases</b>(5)</a>  or  <a href="virtual.5.html"><b>vir-</b></a>
+              The maximal number of addresses remembered  by  the
+              address  duplicate  filter  for  <a href="aliases.5.html"><b>aliases</b>(5)</a> or <a href="virtual.5.html"><b>vir-</b></a>
               <a href="virtual.5.html"><b>tual</b>(5)</a> alias expansion, or for <a href="showq.8.html"><b>showq</b>(8)</a> queue dis-
               plays.
 
@@ -272,16 +273,16 @@ CLEANUP(8)                                                          CLEANUP(8)
               message header.
 
        <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
-              The  maximal  number  of Received:  message headers
+              The maximal number of  Received:   message  headers
               that is allowed in the primary message headers.
 
        <b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
-              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.
 
        <b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
-              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.
 
        <b><a href="postconf.5.html#queue_file_attribute_count_limit">queue_file_attribute_count_limit</a> (100)</b>
-              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:
 
        <b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
-              The  maximal number of addresses that virtual alias
+              The maximal number of addresses that virtual  alias
               expansion produces from each original recipient.
 
        <b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
-              The maximal nesting depth of virtual  alias  expan-
+              The  maximal  nesting depth of virtual alias expan-
               sion.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix main.cf and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              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.
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
-              The maximal number  of  digits  after  the  decimal
+              The  maximal  number  of  digits  after the decimal
               point when logging sub-second delay values.
 
        <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
-              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.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -335,12 +336,12 @@ CLEANUP(8)                                                          CLEANUP(8)
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              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.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The  maximal number of connection requests before a
+              The maximal number of connection requests before  a
               Postfix daemon process terminates.
 
        <b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
@@ -348,19 +349,19 @@ CLEANUP(8)                                                          CLEANUP(8)
 
        <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               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.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The process ID  of  a  Postfix  command  or  daemon
+              The  process  ID  of  a  Postfix  command or daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The  process  name  of  a Postfix command or daemon
+              The process name of a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The location of the Postfix top-level queue  direc-
+              The  location of the Postfix top-level queue direc-
               tory.
 
        <b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
@@ -371,14 +372,14 @@ CLEANUP(8)                                                          CLEANUP(8)
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              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:
 
        <b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
-              Enable  support  for  the   X-Original-To   message
+              Enable   support   for  the  X-Original-To  message
               header.
 
 <b>FILES</b>
@@ -401,7 +402,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> Postfix address manipulation
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index 0bbb27705975719b45f5b40ce14ad1da08cbca5c..5a81f41615baa2f4753bc1841af4307c5a1add3a 100644 (file)
@@ -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 <b>master.cf</b> configuration file.
+       setting in the <a href="master.5.html"><b>master.cf</b></a> configuration file.
 
        Upon  receipt of a request to deliver mail for an eligible
        destination, the <a href="flush.8.html"><b>flush</b>(8)</a> server requests delivery of  all
@@ -81,7 +81,7 @@ FLUSH(8)                                                              FLUSH(8)
        in one domain.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes to <b>main.cf</b> are picked up automatically as <a href="flush.8.html"><b>flush</b>(8)</a>
+       Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="flush.8.html"><b>flush</b>(8)</a>
        processes run for only a limited amount of time.  Use  the
        command "<b>postfix reload</b>" to speed up a change.
 
@@ -89,8 +89,8 @@ FLUSH(8)                                                              FLUSH(8)
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How  much time a Postfix daemon process may take to
index 70e8d8df648691cf15a89712f38828425e63c596..d64cb5bf1be09bbeff29698b6ee8339eecc0dfbc 100644 (file)
@@ -44,7 +44,7 @@ PICKUP(8)                                                            PICKUP(8)
 
 <b>CONFIGURATION PARAMETERS</b>
        As the  <a href="pickup.8.html"><b>pickup</b>(8)</a>  daemon  is  a  relatively  long-running
-       process,  up  to  an hour may pass before a <b>main.cf</b> change
+       process,  up  to  an hour may pass before a <a href="postconf.5.html"><b>main.cf</b></a> change
        takes effect.  Use the command "<b>postfix reload</b>" command to
        speed up a change.
 
@@ -62,8 +62,8 @@ PICKUP(8)                                                            PICKUP(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How  much time a Postfix daemon process may take to
index 57ac66b8b11cdb4a1b671b85ae99b87fb7f57e38..dab7e015ae7934d47c032195f79400e982131f96 100644 (file)
@@ -32,130 +32,139 @@ POSTALIAS(1)                                                      POSTALIAS(1)
        The format of Postfix alias input files  is  described  in
        <a href="aliases.5.html"><b>aliases</b>(5)</a>.
 
+       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  <a href="regexp_table.5.html">regexp</a>: and <a href="pcre_table.5.html">pcre</a>:. This resulted in
+       loss of information with $<i>number</i> substitutions.
+
        Options:
 
        <b>-c</b> <i>config</i><b>_</b><i>dir</i>
-              Read  the  <b>main.cf</b>  configuration file in the named
+              Read the <a href="postconf.5.html"><b>main.cf</b></a> configuration file  in  the  named
               directory  instead  of  the  default  configuration
               directory.
 
-       <b>-d</b> <i>key</i> Search  the  specified  maps for <i>key</i> and remove one
-              entry per map.  The exit status is  zero  when  the
+       <b>-d</b> <i>key</i> Search the specified maps for <i>key</i>  and  remove  one
+              entry  per  map.   The exit status is zero when the
               requested information was found.
 
               If a key value of <b>-</b> 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.
 
        <b>-f</b>     Do not fold the lookup key to lower case while cre-
-              ating or querying a map.
+              ating or querying a table.
 
-       <b>-i</b>     Incremental  mode. Read entries from standard input
+       <b>-i</b>     Incremental mode. Read entries from standard  input
               and  do  not  truncate  an  existing  database.  By
-              default,  <a href="postalias.1.html"><b>postalias</b>(1)</a>  creates a new database from
+              default, <a href="postalias.1.html"><b>postalias</b>(1)</a> creates a new  database  from
               the entries in <i>file</i><b>_</b><i>name</i>.
 
-       <b>-N</b>     Include the terminating null character that  termi-
-              nates  lookup  keys and values. By default, <b>postal-</b>
-              <b>ias</b>(1) does whatever is the default  for  the  host
+       <b>-N</b>     Include  the terminating null character that termi-
+              nates lookup keys and values. By  default,  <b>postal-</b>
+              <b>ias</b>(1)  does  whatever  is the default for the host
               operating system.
 
-       <b>-n</b>     Don't  include  the terminating null character that
-              terminates lookup  keys  and  values.  By  default,
-              <a href="postalias.1.html"><b>postalias</b>(1)</a>  does  whatever is the default for the
+       <b>-n</b>     Don't include the terminating null  character  that
+              terminates  lookup  keys  and  values.  By default,
+              <a href="postalias.1.html"><b>postalias</b>(1)</a> does whatever is the default  for  the
               host operating system.
 
-       <b>-o</b>     Do not release root privileges  when  processing  a
+       <b>-o</b>     Do  not  release  root privileges when processing a
               non-root input file. By default, <a href="postalias.1.html"><b>postalias</b>(1)</a> drops
-              root privileges and runs as the source  file  owner
+              root  privileges  and runs as the source file owner
               instead.
 
        <b>-p</b>     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).
 
-       <b>-q</b> <i>key</i> Search the specified maps for  <i>key</i>  and  write  the
-              first  value  found  to the standard output stream.
+       <b>-q</b> <i>key</i> Search  the  specified  maps  for <i>key</i> 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 <b>-</b> is specified, the program reads
-              key values  from  the  standard  input  stream  and
-              writes  one  line of <i>key: value</i> 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 <i>key: value</i> output for  each  key
+              that  was  found.  The  exit status is zero when at
               least one of the requested keys was found.
 
        <b>-r</b>     When  updating  a  table,  do  not  complain  about
               attempts to update existing entries, and make those
               updates anyway.
 
-       <b>-s</b>     Retrieve  all database elements, and write one line
+       <b>-s</b>     Retrieve all database elements, and write one  line
               of <i>key: value</i> 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.
 
        <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
-              tiple <b>-v</b> options  make  the  software  increasingly
+              tiple  <b>-v</b>  options  make  the software increasingly
               verbose.
 
        <b>-w</b>     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:
 
        <i>file</i><b>_</b><i>type</i>
-              The  database type. To find out what types are sup-
+              The database type. To find out what types are  sup-
               ported, use the "<b>postconf -m</b>" command.
 
-              The <a href="postalias.1.html"><b>postalias</b>(1)</a> command can  query  any  supported
-              file  type,  but  it  can create only the following
+              The  <a href="postalias.1.html"><b>postalias</b>(1)</a>  command  can query any supported
+              file type, but it can  create  only  the  following
               file types:
 
-              <b>btree</b>  The  output   is   a   btree   file,   named
-                     <i>file</i><b>_</b><i>name</i><b>.db</b>.   This is available on systems
+              <b>btree</b>  The   output   is   a   btree   file,  named
+                     <i>file</i><b>_</b><i>name</i><b>.db</b>.  This is available on  systems
                      with support for <b>db</b> databases.
 
-              <b>cdb</b>    The output is one file named  <i>file</i><b>_</b><i>name</i><b>.cdb</b>.
-                     This  is  available  on systems with support
+              <b>cdb</b>    The  output is one file named <i>file</i><b>_</b><i>name</i><b>.cdb</b>.
+                     This is available on  systems  with  support
                      for <b>cdb</b> databases.
 
-              <b>dbm</b>    The output  consists  of  two  files,  named
-                     <i>file</i><b>_</b><i>name</i><b>.pag</b>  and  <i>file</i><b>_</b><i>name</i><b>.dir</b>.   This is
-                     available on systems with  support  for  <b>dbm</b>
+              <b>dbm</b>    The  output  consists  of  two  files, named
+                     <i>file</i><b>_</b><i>name</i><b>.pag</b> and  <i>file</i><b>_</b><i>name</i><b>.dir</b>.   This  is
+                     available  on  systems  with support for <b>dbm</b>
                      databases.
 
-              <b>hash</b>   The   output   is   a   hashed  file,  named
-                     <i>file</i><b>_</b><i>name</i><b>.db</b>.  This is available on  systems
+              <b>hash</b>   The  output  is   a   hashed   file,   named
+                     <i>file</i><b>_</b><i>name</i><b>.db</b>.   This is available on systems
                      with support for <b>db</b> databases.
 
-              <b>sdbm</b>   The  output  consists  of  two  files, named
-                     <i>file</i><b>_</b><i>name</i><b>.pag</b> and  <i>file</i><b>_</b><i>name</i><b>.dir</b>.   This  is
-                     available  on  systems with support for <b>sdbm</b>
+              <b>sdbm</b>   The output  consists  of  two  files,  named
+                     <i>file</i><b>_</b><i>name</i><b>.pag</b>  and  <i>file</i><b>_</b><i>name</i><b>.dir</b>.   This is
+                     available on systems with support  for  <b>sdbm</b>
                      databases.
 
-              When no <i>file</i><b>_</b><i>type</i> is specified, the  software  uses
-              the  database  type specified via the <b><a href="postconf.5.html#default_database_type">default_data</a>-</b>
+              When  no  <i>file</i><b>_</b><i>type</i> is specified, the software uses
+              the database type specified via  the  <b><a href="postconf.5.html#default_database_type">default_data</a>-</b>
               <b><a href="postconf.5.html#default_database_type">base_type</a></b>  configuration  parameter.   The  default
-              value  for this parameter depends on the host envi-
+              value for this parameter depends on the host  envi-
               ronment.
 
        <i>file</i><b>_</b><i>name</i>
-              The name of the alias  database  source  file  when
+              The  name  of  the  alias database source file when
               creating a database.
 
 <b>DIAGNOSTICS</b>
-       Problems  are  logged  to the standard error stream and to
-       <b>syslogd</b>(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
+       <b>syslogd</b>(8).    No  output  means  that  no  problems  were
+       detected. Duplicate entries are skipped  and  are  flagged
        with a warning.
 
-       <a href="postalias.1.html"><b>postalias</b>(1)</a> terminates with zero exit status in  case  of
-       success  (including  successful "<b>postalias -q</b>" lookup) and
+       <a href="postalias.1.html"><b>postalias</b>(1)</a>  terminates  with zero exit status in case of
+       success (including successful "<b>postalias -q</b>"  lookup)  and
        terminates with non-zero exit status in case of failure.
 
 <b>ENVIRONMENT</b>
@@ -166,26 +175,26 @@ POSTALIAS(1)                                                      POSTALIAS(1)
               Enable verbose logging for debugging purposes.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
        to this program.
 
-       The  text  below  provides  only  a parameter summary. See
+       The text below provides  only  a  parameter  summary.  See
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#alias_database">alias_database</a> (see 'postconf -d' output)</b>
-              The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that  are
+              The  alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are
               updated with "<b>newaliases</b>" or with "<b>sendmail -bi</b>".
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix main.cf and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#berkeley_db_create_buffer_size">berkeley_db_create_buffer_size</a> (16777216)</b>
-              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.
 
        <b><a href="postconf.5.html#berkeley_db_read_buffer_size">berkeley_db_read_buffer_size</a> (131072)</b>
-              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.
 
        <b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
@@ -196,8 +205,8 @@ POSTALIAS(1)                                                      POSTALIAS(1)
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              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".
 
 <b>STANDARDS</b>
@@ -216,7 +225,7 @@ POSTALIAS(1)                                                      POSTALIAS(1)
        <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index 6a8686f24da1ebc5c8a58f52bbcd77b5f7fe7e53..804da530c950e2f3d133dbd75d5b736f51159fd4 100644 (file)
@@ -1927,7 +1927,8 @@ Do not change this unless you have a complete understanding of <a href="http://w
 (default: defer)</b></DT><DD>
 
 <p>
-The name of the <a href="defer.8.html">defer(8)</a> service. This service maintains a record
+The name of the defer service. This service is implemented by the
+<a href="bounce.8.html">bounce(8)</a> daemon and maintains a record
 of failed delivery attempts and generates non-delivery notifications.
 </p>
 
@@ -5172,7 +5173,7 @@ This feature is available in Postfix 2.0 and later.
 
 </DD>
 
-<DT><b><a name="plaintext_session_reject_code">plaintext_session_reject_code</a>
+<DT><b><a name="plaintext_reject_code">plaintext_reject_code</a>
 (default: 450)</b></DT><DD>
 
 <p>
@@ -7552,71 +7553,77 @@ postfix/smtp[pid]:  Host offered STARTTLS: [name.of.host]
 (default: empty)</b></DT><DD>
 
 <p> Optional lookup tables with the Postfix SMTP client TLS usage
-policy by next-hop domain name and by remote SMTP server hostname.
-</p>
-
-<p> 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:  </p>
+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).  </p>
+
+<p> 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 <a href="transport.5.html">transport(5)</a>
+table, the <a href="postconf.5.html#relayhost">relayhost</a> parameter, or the <a href="postconf.5.html#relay_transport">relay_transport</a> parameter.
+On the right hand side specify one of the following keywords:  </p>
 
 <dl>
 
-<dt> NONE </dt> <dd>Don't use TLS at all. </dd>
-
-<dt> MAY </dt> <dd>Try to use STARTTLS if offered, otherwise use
-the unencrypted connection. </dd>
-
-<dt> MUST </dt> <dd>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. </dd>
-
-<dt> MUST_NOPEERMATCH </dt> <dd>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. </dd>
+<dt> NONE </dt> <dd> Don't use TLS at all. This overrides a less
+specific <b>MAY</b> lookup result from the alternate host or next-hop
+lookup key, and overrides the global <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>, <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>,
+and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> settings. </dd>
+
+<dt> MAY </dt> <dd> Try to use TLS if the server announces support,
+otherwise use the unencrypted connection. This has less precedence
+than a more specific result (including <b>NONE</b>) from the alternate
+host or next-hop lookup key, and has less precedence than the more
+specific global "<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes" or "<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
+= yes".  </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd> 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 <b>NONE</b>
+or a less specific <b>MAY</b> lookup result from the alternate host
+or next-hop lookup key, and overrides the global <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>,
+<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> settings.  </dd>
+
+<dt> MUST </dt> <dd> 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 <b>NONE</b>
+and <b>MUST_NOPEERMATCH</b> or a less specific <b>MAY</b> lookup
+result from the alternate host or next-hop lookup key, and overrides
+the global <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>, <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
+settings.  </dd>
 
 </dl>
 
-<p> Special hints for enforcement mode:  since no secure DNS lookup
-mechanism is available, the recommended setup is:  </p>
-
-<dl>
-
-<dt> Postfix 2.2.9 </dt>
-
-<dd> <ul>
-
-<li> Specify "<a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> = no". This avoids
-false hostname information in DNS CNAME records that could bypass
-a hostname-based TLS usage policy.
+<p> 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: </p>
 
-<li> Specify local <a href="transport.5.html">transport(5)</a> table entries for sensitive domains
-with explicit <a href="smtp.8.html">smtp</a>:[mailhost] destinations. This avoids false
-hostname information in DNS MX records that could bypass a
-hostname-based TLS usage policy.
-
-<li> Specify MUST for these mail hosts in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
-table.
-
-</ul> </dd>
-
-<dt> Postfix &lt; 2.2.9 </dt>
-
-<dd> <ul>
+<ul>
 
-<li> Specify local <a href="transport.5.html">transport(5)</a> table entries for sensitive domains
-with explicit <a href="smtp.8.html">smtp</a>:[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.
+<li> Disallow CNAME hostname overrides. In <a href="postconf.5.html">main.cf</a> specify
+"<a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> = 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.
 
-<li> Specify MUST for these mail hosts in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
-table.
+<li> Eliminate MX lookups. Specify local <a href="transport.5.html">transport(5)</a> table entries
+for sensitive domains with explicit <a href="smtp.8.html">smtp</a>:[mailhost] or <a href="smtp.8.html">smtp</a>:[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.
 
-</ul> </dd>
+<li> Specify MUST for these mail hosts (including [ ] and port) in
+the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table.
 
-</dl>
+</ul>
 
 <p> </p>
 
@@ -8199,9 +8206,11 @@ a restriction list, to make the default policy explicit.</dd>
 <dt><b><a name="reject_multi_recipient_bounce">reject_multi_recipient_bounce</a></b></dt>
 
 <dd>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. <br> 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.
+<br> Note: this restriction can only work reliably
 when used in <a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> or
 <a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a>, 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. </dd>
 restriction should not be used before the client has had a chance
 to negotiate encryption with the AUTH or STARTTLS commands.
 <br>
-The <a href="postconf.5.html#plaintext_session_reject_code">plaintext_session_reject_code</a> parameter specifies the response
+The <a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> parameter specifies the response
 code for rejected requests (default:  450).  This feature is available
 in Postfix 2.3 and later. </dd>
 
@@ -10283,7 +10292,8 @@ gives timeout errors.  </p>
 (default: trace)</b></DT><DD>
 
 <p>
-The name of the <a href="trace.8.html">trace(8)</a> service. This service maintains a record
+The name of the trace service. This service is implemented by the
+<a href="bounce.8.html">bounce(8)</a> daemon and maintains a record
 of mail deliveries and produces a mail delivery report when verbose
 delivery is requested with "<b>sendmail -v</b>".
 </p>
index 4510e9e207eef13470dff9acf327bc3d1669f506..5eec30834881a05651d9444433318b07576b5c92 100644 (file)
@@ -19,7 +19,7 @@ POSTDROP(1)                                                        POSTDROP(1)
        Options:
 
        <b>-c</b> <i>config</i><b>_</b><i>dir</i>
-              The <b>main.cf</b> configuration  file  is  in  the  named
+              The <a href="postconf.5.html"><b>main.cf</b></a> configuration  file  is  in  the  named
               directory  instead  of  the  default  configuration
               directory. See  also  the  MAIL_CONFIG  environment
               setting below.
@@ -49,18 +49,18 @@ POSTDROP(1)                                                        POSTDROP(1)
 
 <b>ENVIRONMENT</b>
        MAIL_CONFIG
-              Directory with the <b>main.cf</b> file. In order to  avoid
+              Directory with the <a href="postconf.5.html"><b>main.cf</b></a> file. In order to  avoid
               exploitation  of  set-group  ID  privileges, a non-
               standard directory is allowed only if:
 
-              <b>o</b>      The name is listed in the  standard  <b>main.cf</b>
+              <b>o</b>      The name is listed in the  standard  <a href="postconf.5.html"><b>main.cf</b></a>
                      file  with  the <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
                      configuration parameter.
 
               <b>o</b>      The command is invoked by the super-user.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
+       The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are  especially  relevant
        to this program.  The text below provides only a parameter
        summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including  exam-
        ples.
@@ -72,8 +72,8 @@ POSTDROP(1)                                                        POSTDROP(1)
               environment parameter.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
               The  list  of environment parameters that a Postfix
index ed2e90e7561fc36dce9f421ff5f1a269d7e24ed2..53d86f0b32a4c01de09886185fd3815a7736a49a 100644 (file)
@@ -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  <i>key</i>  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  <a href="regexp_table.5.html">regexp</a>: and <a href="pcre_table.5.html">pcre</a>:. This resulted in
+       loss of information with $<i>number</i> substitutions.
 
 <b>COMMAND-LINE ARGUMENTS</b>
        <b>-c</b> <i>config</i><b>_</b><i>dir</i>
-              Read the <b>main.cf</b> configuration file  in  the  named
+              Read the <a href="postconf.5.html"><b>main.cf</b></a> configuration file  in  the  named
               directory  instead  of  the  default  configuration
               directory.
 
@@ -68,7 +76,7 @@ POSTMAP(1)                                                          POSTMAP(1)
               keys was found.
 
        <b>-f</b>     Do not fold the lookup key to lower case while cre-
-              ating or querying a map.
+              ating or querying a table.
 
        <b>-i</b>     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.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The  following  <b>main.cf</b> parameters are especially relevant
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
        to this program.  The text below provides only a parameter
        summary.  See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
        ples.
@@ -197,8 +205,8 @@ POSTMAP(1)                                                          POSTMAP(1)
               read Berkeley DB hash or btree tables.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
               The default database type for use in <a href="newaliases.1.html"><b>newaliases</b>(1)</a>,
index 29a64ee79f97d37083909be5549f3acd35f4ca29..b1885010062db06bbd352f7dd4cf39aa3d056a01 100644 (file)
@@ -25,7 +25,7 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
        The following options are recognized:
 
        <b>-c</b> <i>config</i><b>_</b><i>dir</i>
-              The <b>main.cf</b> configuration  file  is  in  the  named
+              The <a href="postconf.5.html"><b>main.cf</b></a> configuration  file  is  in  the  named
               directory  instead  of  the  default  configuration
               directory. See  also  the  MAIL_CONFIG  environment
               setting below.
@@ -89,18 +89,18 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
 
 <b>ENVIRONMENT</b>
        MAIL_CONFIG
-              Directory with the <b>main.cf</b> file. In order to  avoid
+              Directory with the <a href="postconf.5.html"><b>main.cf</b></a> file. In order to  avoid
               exploitation  of  set-group  ID  privileges, a non-
               standard directory is allowed only if:
 
-              <b>o</b>      The name is listed in the  standard  <b>main.cf</b>
+              <b>o</b>      The name is listed in the  standard  <a href="postconf.5.html"><b>main.cf</b></a>
                      file  with  the <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
                      configuration parameter.
 
               <b>o</b>      The command is invoked by the super-user.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
+       The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are  especially  relevant
        to this program.  The text below provides only a parameter
        summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including  exam-
        ples.
@@ -112,8 +112,8 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
               environment parameter.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
               The  location  of  all  postfix administrative com-
index 6f72fc5fe01f1667b908ceb6a37410a4117b68bf..57eca5eb40e30cf6a49e5b692619f3b41bb4f832 100644 (file)
@@ -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  <a href="postconf.5.html">main.cf</a> setting to be used by sensitive and non-sen-
        sitive processes.
 
 <b>DIAGNOSTICS</b>
@@ -96,15 +96,15 @@ PROXYMAP(8)                                                        PROXYMAP(8)
 
 <b>CONFIGURATION PARAMETERS</b>
        On busy mail systems a long time  may  pass  before  <a href="proxymap.8.html"><b>prox-</b></a>
-       <a href="proxymap.8.html"><b>ymap</b>(8)</a> relevant changes to <b>main.cf</b> are picked up. Use the
+       <a href="proxymap.8.html"><b>ymap</b>(8)</a> relevant changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up. Use the
        command "<b>postfix reload</b>" to speed up a change.
 
        The text below provides  only  a  parameter  summary.  See
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix main.cf and
-              master.cf configuration files.
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How much time a Postfix daemon process may take  to
index 89a21f4b740ac15399ac46c426a5c560420297a6..8f244435a7086a7f6c9a7dba95682d5b8fd67e12 100644 (file)
@@ -43,7 +43,7 @@ QMQPD(8)                                                              QMQPD(8)
        is left up to the client to handle the situation.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes   to  <b>main.cf</b>  are  picked  up  automatically,  as
+       Changes   to  <a href="postconf.5.html"><b>main.cf</b></a>  are  picked  up  automatically,  as
        <a href="qmqpd.8.html"><b>qmqpd</b>(8)</a> processes run for only a limited amount of  time.
        Use the command "<b>postfix reload</b>" to speed up a change.
 
@@ -100,8 +100,8 @@ QMQPD(8)                                                              QMQPD(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How  much time a Postfix daemon process may take to
index c5f6621efbe06fa2320d7158149e5e7f9e816215..868e14f53213d2b3b46d90473cf2c8b43318d1a8 100644 (file)
@@ -86,7 +86,7 @@ SCACHE(8)                                                            SCACHE(8)
        without the appropriate protocol specific handshake.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes  to  <b>main.cf</b>  are  picked  up   automatically   as
+       Changes  to  <a href="postconf.5.html"><b>main.cf</b></a>  are  picked  up   automatically   as
        <a href="scache.8.html"><b>scache</b>(8)</a> processes run for only a limited amount of time.
        Use the command "<b>postfix reload</b>" to speed up a change.
 
@@ -106,8 +106,8 @@ SCACHE(8)                                                            SCACHE(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix main.cf and
-              master.cf configuration files.
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How much time a Postfix daemon process may take  to
index faa2317e4c71d9b3522e7b5c6d2a546020ad3d1c..c2e465ded725408e06248b7b060029be1ee0d063 100644 (file)
@@ -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 <b>main.cf</b> configu-
+       tures are controlled by parameters in the <a href="postconf.5.html"><b>main.cf</b></a> configu-
        ration file.
 
        The following options are recognized:
@@ -110,57 +110,58 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <b>-C</b> <i>config</i><b>_</b><i>file</i>
 
        <b>-C</b> <i>config</i><b>_</b><i>dir</i>
-              The  path  name  of the Postfix <b>main.cf</b> file, or of
+              The  path  name  of the Postfix <a href="postconf.5.html"><b>main.cf</b></a> 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.
 
        <b>-F</b> <i>full</i><b>_</b><i>name</i>
-              Set  the  sender  full name. This is used only with
+              Set the sender full name. This is  used  only  with
               messages that have no <b>From:</b> message header.
 
        <b>-f</b> <i>sender</i>
               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 <b>Errors-To:</b> message
               header overrides the error return address.
 
-       <b>-G</b>     Gateway  (relay)  submission, as opposed to initial
-              user submission.  Either do not  rewrite  addresses
-              at  all,  or  update  incomplete addresses with the
+       <b>-G</b>     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 <b>remote_header_re-</b>
               <b>write_domain</b>.
 
-              This  option is ignored before Postfix version 2.3.
+              This option is ignored before Postfix version  2.3.
 
        <b>-h</b> <i>hop</i><b>_</b><i>count</i> (ignored)
-              Hop count limit. Use the <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a></b>  configura-
+              Hop  count limit. Use the <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a></b> configura-
               tion parameter instead.
 
-       <b>-I</b>     Initialize  alias database. See the <b>newaliases</b> com-
+       <b>-I</b>     Initialize alias database. See the <b>newaliases</b>  com-
               mand above.
 
-       <b>-i</b>     When reading a message from standard  input,  don't
-              treat  a line with only a <b>.</b> character as the end of
+       <b>-i</b>     When  reading  a message from standard input, don't
+              treat a line with only a <b>.</b> character as the end  of
               input.
 
        <b>-L</b> <i>label</i> (ignored)
-              The logging label. Use the  <b><a href="postconf.5.html#syslog_name">syslog_name</a></b>  configura-
+              The  logging  label. Use the <b><a href="postconf.5.html#syslog_name">syslog_name</a></b> configura-
               tion parameter instead.
 
        <b>-m</b> (ignored)
               Backwards compatibility.
 
        <b>-N</b> <i>dsn</i> (default: 'delay, failure')
-              Delivery   status   notification  control.  Specify
-              either a comma-separated list with one or  more  of
-              <b>failure</b>  (send  notification  when delivery fails),
+              Delivery  status  notification   control.   Specify
+              either  a  comma-separated list with one or more of
+              <b>failure</b> (send notification  when  delivery  fails),
               <b>delay</b> (send notification when delivery is delayed),
-              or  <b>success</b>  (send notification when the message is
-              delivered); or specify <b>never</b> (don't send any  noti-
+              or <b>success</b> (send notification when the  message  is
+              delivered);  or specify <b>never</b> (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.
 
        <b>-oA</b><i>alias</i><b>_</b><i>database</i>
-              Non-default alias  database.  Specify  <i>pathname</i>  or
+              Non-default  alias  database.  Specify  <i>pathname</i> or
               <i>type</i>:<i>pathname</i>. See <a href="postalias.1.html"><b>postalias</b>(1)</a> for details.
 
        <b>-O</b> <i>option=value</i> (ignored)
@@ -179,60 +180,60 @@ SENDMAIL(1)                                                        SENDMAIL(1)
 
        <b>-o8</b> (ignored)
               To send 8-bit or binary content, use an appropriate
-              MIME encapsulation and specify the  appropriate  <b>-B</b>
+              MIME  encapsulation  and specify the appropriate <b>-B</b>
               command-line option.
 
-       <b>-oi</b>    When  reading  a message from standard input, don't
-              treat a line with only a <b>.</b> character as the end  of
+       <b>-oi</b>    When reading a message from standard  input,  don't
+              treat  a line with only a <b>.</b> character as the end of
               input.
 
        <b>-om</b> (ignored)
-              The  sender  is  never  eliminated  from alias etc.
+              The sender is  never  eliminated  from  alias  etc.
               expansions.
 
        <b>-o</b> <i>x value</i> (ignored)
-              Set option <i>x</i> to <i>value</i>. Use the equivalent  configu-
-              ration parameter in <b>main.cf</b> instead.
+              Set  option <i>x</i> to <i>value</i>. Use the equivalent configu-
+              ration parameter in <a href="postconf.5.html"><b>main.cf</b></a> instead.
 
        <b>-r</b> <i>sender</i>
               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 <b>Errors-To:</b> message
               header overrides the error return address.
 
        <b>-R</b> <i>return</i><b>_</b><i>limit</i> (ignored)
-              Limit  the  size   of   bounced   mail.   Use   the
-              <b><a href="postconf.5.html#bounce_size_limit">bounce_size_limit</a></b>  configuration parameter instead.
+              Limit   the   size   of   bounced   mail.  Use  the
+              <b><a href="postconf.5.html#bounce_size_limit">bounce_size_limit</a></b> configuration parameter  instead.
 
-       <b>-q</b>     Attempt to deliver all queued mail. This is  imple-
+       <b>-q</b>     Attempt  to deliver all queued mail. This is imple-
               mented by executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command.
 
               Warning:  flushing  undeliverable  mail  frequently
-              will result in poor  delivery  performance  of  all
+              will  result  in  poor  delivery performance of all
               other mail.
 
        <b>-q</b><i>interval</i> (ignored)
-              The   interval   between   queue   runs.   Use  the
+              The  interval   between   queue   runs.   Use   the
               <b><a href="postconf.5.html#queue_run_delay">queue_run_delay</a></b> configuration parameter instead.
 
        <b>-qR</b><i>site</i>
-              Schedule immediate delivery of  all  mail  that  is
+              Schedule  immediate  delivery  of  all mail that is
               queued for the named <i>site</i>. This option accepts only
-              <i>site</i> names that are eligible for the  "fast  flush"
-              service,   and  is  implemented  by  executing  the
+              <i>site</i>  names  that are eligible for the "fast flush"
+              service,  and  is  implemented  by  executing   the
               <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command.  See <a href="flush.8.html"><b>flush</b>(8)</a> for more infor-
               mation about the "fast flush" service.
 
        <b>-qS</b><i>site</i>
-              This  command  is  not  implemented. Use the slower
+              This command is not  implemented.  Use  the  slower
               "<b>sendmail -q</b>" command instead.
 
-       <b>-t</b>     Extract recipients from message headers. These  are
-              added  to  any  recipients specified on the command
+       <b>-t</b>     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.
 
        <b>-U</b> (ignored)
@@ -245,41 +246,41 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               This feature is available in Postfix 2.3 and later.
 
        <b>-XV</b> (Postfix 2.2 and earlier: <b>-V</b>)
-              Variable Envelope Return Path.  Given  an  envelope
-              sender  address  of the form <i>owner-listname</i>@<i>origin</i>,
-              each recipient <i>user</i>@<i>domain</i>  receives  mail  with  a
+              Variable  Envelope  Return  Path. Given an envelope
+              sender address of the  form  <i>owner-listname</i>@<i>origin</i>,
+              each  recipient  <i>user</i>@<i>domain</i>  receives  mail with a
               personalized envelope sender address.
 
-              By   default,   the  personalized  envelope  sender
-              address is  <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>.  The
-              default  <b>+</b>  and  <b>=</b> characters are configurable with
-              the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>  configuration  parame-
+              By  default,  the  personalized   envelope   sender
+              address  is  <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>. The
+              default <b>+</b> and <b>=</b> characters  are  configurable  with
+              the  <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>  configuration parame-
               ter.
 
        <b>-XV</b><i>xy</i> (Postfix 2.2 and earlier: <b>-V</b><i>xy</i>)
-              As  <b>-XV</b>,  but  uses  <i>x</i>  and <i>y</i> as the VERP delimiter
-              characters, instead  of  the  characters  specified
-              with   the   <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>  configuration
+              As <b>-XV</b>, but uses <i>x</i> and  <i>y</i>  as  the  VERP  delimiter
+              characters,  instead  of  the  characters specified
+              with  the   <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>   configuration
               parameter.
 
-       <b>-v</b>     Send an email report of the first delivery  attempt
-              (Postfix  versions  2.1  and  later). Mail delivery
-              always happens in the background. When multiple  <b>-v</b>
+       <b>-v</b>     Send  an email report of the first delivery attempt
+              (Postfix versions 2.1  and  later).  Mail  delivery
+              always  happens in the background. When multiple <b>-v</b>
               options  are  given,  enable  verbose  logging  for
               debugging purposes.
 
        <b>-X</b> <i>log</i><b>_</b><i>file</i> (ignored)
-              Log mailer traffic.  Use  the  <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></b>  and
-              <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a></b>  configuration parameters instead.
+              Log  mailer  traffic.  Use  the <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></b> and
+              <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a></b> configuration parameters  instead.
 
 <b>SECURITY</b>
-       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.
 
 <b>DIAGNOSTICS</b>
-       Problems  are  logged  to  <b>syslogd</b>(8)  and to the standard
+       Problems are logged to  <b>syslogd</b>(8)  and  to  the  standard
        error stream.
 
 <b>ENVIRONMENT</b>
@@ -291,17 +292,17 @@ SENDMAIL(1)                                                        SENDMAIL(1)
 
        <b>MAIL_DEBUG</b>
               Enable debugging with an external command, as spec-
-              ified   with   the  <b><a href="postconf.5.html#debugger_command">debugger_command</a></b>  configuration
+              ified  with  the   <b><a href="postconf.5.html#debugger_command">debugger_command</a></b>   configuration
               parameter.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
        to this program.  The text below provides only a parameter
-       summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including  exam-
+       summary.  See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
        ples.
 
 <b>TROUBLE SHOOTING CONTROLS</b>
-       The  <a href="DEBUG_README.html">DEBUG_README</a>  file  gives  examples of how to trouble
+       The <a href="DEBUG_README.html">DEBUG_README</a> file gives examples  of  how  to  trouble
        shoot a Postfix system.
 
        <b><a href="postconf.5.html#debugger_command">debugger_command</a> (empty)</b>
@@ -309,29 +310,29 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               mon program is invoked with the -D option.
 
        <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
-              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
               <a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
 
        <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
-              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 $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
 
 <b>ACCESS CONTROLS</b>
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> (static:anyone)</b>
-              List of users  who  are  authorized  to  flush  the
+              List  of  users  who  are  authorized  to flush the
               queue.
 
        <b><a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a> (static:anyone)</b>
               List of users who are authorized to view the queue.
 
        <b><a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> (static:anyone)</b>
-              List of users who are  authorized  to  submit  mail
-              with  the  <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command (and with the privi-
+              List  of  users  who  are authorized to submit mail
+              with the <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command (and with  the  privi-
               leged <a href="postdrop.1.html"><b>postdrop</b>(1)</a> helper command).
 
 <b>RESOURCE AND RATE CONTROLS</b>
@@ -340,7 +341,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               sent in a non-delivery notification.
 
        <b><a href="postconf.5.html#fork_attempts">fork_attempts</a> (5)</b>
-              The  maximal  number  of attempts to fork() a child
+              The maximal number of attempts to  fork()  a  child
               process.
 
        <b><a href="postconf.5.html#fork_delay">fork_delay</a> (1s)</b>
@@ -348,11 +349,11 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               process.
 
        <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
-              The  maximal  number  of Received:  message headers
+              The maximal number of  Received:   message  headers
               that is allowed in the primary message headers.
 
        <b><a href="postconf.5.html#queue_run_delay">queue_run_delay</a> (1000s)</b>
-              The time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the  queue
+              The  time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the queue
               manager.
 
 <b>FAST FLUSH CONTROLS</b>
@@ -361,37 +362,37 @@ SENDMAIL(1)                                                        SENDMAIL(1)
 
        <b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
               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.
 
 <b>VERP CONTROLS</b>
        The <a href="VERP_README.html">VERP_README</a> file describes configuration and operation
-       details  of  Postfix  support for variable envelope return
+       details of Postfix support for  variable  envelope  return
        path addresses.
 
        <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a> (+=)</b>
               The two default VERP delimiter characters.
 
        <b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
-              The characters Postfix accepts  as  VERP  delimiter
-              characters  on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
+              The  characters  Postfix  accepts as VERP delimiter
+              characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command  line
               and in SMTP commands.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#alias_database">alias_database</a> (see 'postconf -d' output)</b>
-              The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that  are
+              The  alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are
               updated with "<b>newaliases</b>" or with "<b>sendmail -bi</b>".
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
-              The  location  of  all  postfix administrative com-
+              The location of  all  postfix  administrative  com-
               mands.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_directory">daemon_directory</a> (see 'postconf -d' output)</b>
-              The  directory  with  Postfix  support programs and
+              The directory with  Postfix  support  programs  and
               daemon programs.
 
        <b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
@@ -399,16 +400,17 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               <a href="postalias.1.html"><b>postalias</b>(1)</a> and <a href="postmap.1.html"><b>postmap</b>(1)</a> commands.
 
        <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
-              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.
 
        <b><a href="postconf.5.html#enable_errors_to">enable_errors_to</a> (no)</b>
-              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).
 
        <b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
               The UNIX system account that owns the Postfix queue
index 371d10f562bf0094028eea89d664a6cbfe8fbb75..303b46bfdac0e83f207ad822315e8ca5810a508a 100644 (file)
@@ -821,7 +821,7 @@ SMTPD(8)                                                              SMTPD(8)
               <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
               restriction.
 
-       <b>plaintext_reject_code (450)</b>
+       <b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b>
               The  numerical  Postfix  SMTP  server response code
               when a request is  rejected  by  the  <b>reject_plain-</b>
               <b>text_session</b> restriction.
index c7e00723051ce12ac3f19d8ed0159c85e0505c0d..e2b15e73e526e1369a773ff59d13604d0714cf5b 100644 (file)
@@ -56,7 +56,7 @@ TLSMGR(8)                                                            TLSMGR(8)
        files.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes  to  <b>main.cf</b>  are  not  picked  up  automatically,
+       Changes  to  <a href="postconf.5.html"><b>main.cf</b></a>  are  not  picked  up  automatically,
        because <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> is a persistent processes.  Use the com-
        mand "<b>postfix reload</b>" after a configuration change.
 
@@ -108,8 +108,8 @@ TLSMGR(8)                                                            TLSMGR(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How  much time a Postfix daemon process may take to
index 007e70dd7a8a98102fb2a0019082d464cb9aea84..2e045a1e60b3f5029fb34c1f45086b6e401b426e 100644 (file)
@@ -43,7 +43,7 @@ TRIVIAL-REWRITE(8)                                          TRIVIAL-REWRITE(8)
 
               <i>transport</i>
                      The delivery agent to use. This is the first
-                     field of an entry in the <b>master.cf</b> file.
+                     field of an entry in the <a href="master.5.html"><b>master.cf</b></a> file.
 
               <i>nexthop</i>
                      The host to send to  and  optional  delivery
@@ -85,7 +85,7 @@ TRIVIAL-REWRITE(8)                                          TRIVIAL-REWRITE(8)
        Problems and transactions are logged to <b>syslogd</b>(8).
 
 <b>CONFIGURATION PARAMETERS</b>
-       On busy mail systems a long time may pass before a <b>main.cf</b>
+       On busy mail systems a long time may pass before a <a href="postconf.5.html"><b>main.cf</b></a>
        change  affecting <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> is picked up. Use the
        command "<b>postfix reload</b>" to speed up a change.
 
@@ -234,8 +234,8 @@ TRIVIAL-REWRITE(8)                                          TRIVIAL-REWRITE(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How  much time a Postfix daemon process may take to
index 2af3c6a2dc6ca6c960541ef5f2ae4d489e97dd1d..a78b7914c0033773d277ba8dfbbd3d5600a27baf 100644 (file)
@@ -152,7 +152,7 @@ VIRTUAL(8)                                                          VIRTUAL(8)
        maintaining three tables, use an LDAP or MYSQL database.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes  to  <b>main.cf</b>  are picked up automatically, as <a href="virtual.8.html"><b>vir-</b></a>
+       Changes  to  <a href="postconf.5.html"><b>main.cf</b></a>  are picked up automatically, as <a href="virtual.8.html"><b>vir-</b></a>
        <a href="virtual.8.html"><b>tual</b>(8)</a> processes run for only a limited amount  of  time.
        Use the command "<b>postfix reload</b>" to speed up a change.
 
@@ -191,9 +191,9 @@ VIRTUAL(8)                                                          VIRTUAL(8)
               <a href="postconf.5.html#virtual_transport">tual_transport</a> mail delivery transport.
 
        <b><a href="postconf.5.html#virtual_transport">virtual_transport</a> (virtual)</b>
-              The default mail  delivery  transport  for  domains
-              that  match  the $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> parameter
-              value.
+              The default mail delivery  transport  and  next-hop
+              destination  for  final  delivery to domains listed
+              with $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
 
 <b>LOCKING CONTROLS</b>
        <b><a href="postconf.5.html#virtual_mailbox_lock">virtual_mailbox_lock</a> (see 'postconf -d' output)</b>
@@ -230,8 +230,8 @@ VIRTUAL(8)                                                          VIRTUAL(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
               How  much time a Postfix daemon process may take to
index 99c7daaf5b44f342e7acf86c33f094be1bfb5ce6..31e948f6ffa152fa032934823743994b256910ef 100644 (file)
@@ -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 - $? >$@
index 1c80de7e2b03e04cd31103e97c44f2fb80056727..c8bd57491a2ad83a02dbade8dab78601e0c0b8fd 100644 (file)
@@ -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
index 0674e23acce1b88da8df8c9e3c5c472e677669f6..dc3e9bce73a837e5a12a7202bf545cb3c57ec3ae 100644 (file)
@@ -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
index 92f7e3a5cf38c36005191477aa8fe43c8a05edd3..eba9b7f5436e21efd478880f78bd4cbbacdd66bb 100644 (file)
@@ -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
index ddde62dd4564c6ac5714e80a793c80581b8e2cfc..50957950384ac94766a01ff462b098096246a351 100644 (file)
@@ -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.
-.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:
+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
+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.
-.PP
-Special hints for enforcement mode:  since no secure DNS lookup
-mechanism is available, the recommended setup is:
-.IP "Postfix 2.2.9"
-.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.
-.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.
+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
+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 MUST for these mail hosts in the smtp_tls_per_site
-table.
-.IP "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.
 .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.
+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.
+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
index 8e2dad32aff2b4a90f9d03e8c6df08834936e35b..558a6b7d5a0c395d95b2dd98c5628b00ee3fd6ee 100644 (file)
@@ -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
index ca3b7616331a6d13a1d27278728a17185bdcb857..389e578a473557d3e2f52939384049c4cf3aaa69 100644 (file)
@@ -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 (executable)
index 0000000..cc120de
--- /dev/null
@@ -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
index 8af68581fd67bc4b745d58a1250722dcd9c1cbac..1b48da42e625cb89302cc910d67d4750207eac12 100755 (executable)
@@ -293,7 +293,7 @@ while (<>) {
     s;\bpar[-</bB>]*\n* *[<bB>]*ent_domain_matches_subdomains\b;<a href="postconf.5.html#parent_domain_matches_subdomains">$&</a>;g;
     s;\bpermit_mx_backup_networks\b;<a href="postconf.5.html#permit_mx_backup_networks">$&</a>;g;
     s;\bpickup_service_name\b;<a href="postconf.5.html#pickup_service_name">$&</a>;g;
-    s;\bplaintext_session_reject_code\b;<a href="postconf.5.html#plaintext_session_reject_code">$&</a>;g;
+    s;\bplaintext_reject_code\b;<a href="postconf.5.html#plaintext_reject_code">$&</a>;g;
     s;\bprepend_delivered_header\b;<a href="postconf.5.html#prepend_delivered_header">$&</a>;g;
     s;\bprocess_id\b;<a href="postconf.5.html#process_id">$&</a>;g;
     s;\bprocess_id_directory\b;<a href="postconf.5.html#process_id_directory">$&</a>;g;
index 5777e7573ce49fab2a7f1c2fc648d4fd3e9826b9..fd56bdc2ef03ffa7965babcf97429d0b8d7e924f 100644 (file)
@@ -54,7 +54,7 @@ available from http://www.corpit.ru/mjt/tinycdb.html. </p>
 <p>  Tinycdb is preferred, since it is a bit faster, has additional
 useful functionality and is much simpler to use. </p>
 
-<p>To build Postfix after you have installed CDB, use something
+<p>To build Postfix after you have installed tinycdb, use something
 like: </p>
 
 <blockquote>
@@ -65,7 +65,11 @@ like: </p>
     "AUXLIBS=$CDB/libcdb.a"
 % make
 </pre>
-for tinycdb, or alternatively, for the D.J.B. version:<br>
+</blockquote>
+
+<p> Alternatively, for the D.J.B. version of CDB:<p>
+
+<blockquote>
 <pre>
 % make tidy
 % CDB=../../../cdb-0.75
index 8e8a708367f887d709d387ef19f200fbc1e6d28b..f9c60d5a8761a7c11fc1a5f722acf8e0b597cba7 100644 (file)
@@ -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
     </p>
 
     <li> <p> When an attribute value is unavailable, the client
-    either does not send the attribute, or sends the attribute with
-    an empty value ("name="). </p>
+    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. </p>
+
+    <li> <p> 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.
+    </p>
+
+    <li> <p> 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.  </p>
 
     <li> <p> 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.
index 20154a37fea4c49b363080f8fba1470679e6f865..3888598e445a6f255db17c4b2dfbbebfb747b6f3 100644 (file)
@@ -129,6 +129,11 @@ the <tt>make(1)</tt> files with the necessary definitions. This is
 done by invoking the command "<tt>make makefiles</tt>" in the Postfix
 top-level directory and with arguments as shown next. </p>
 
+<p> <b> 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.
+</b> </p>
+
 <ul>
 
 <li> <p> If the OpenSSL include files (such as <tt>ssl.h</tt>) are
@@ -726,9 +731,23 @@ key configuration </a>
 
 <li><a href="#client_tls_cache">Client-side TLS session cache</a>
 
-<li><a href="#client_tls"> Enabling TLS in the Postfix SMTP client </a>
+<li><a href="#client_tls_enable"> Enabling TLS in the Postfix SMTP client </a>
+
+<li><a href="#client_tls_require"> Requiring TLS encryption </a>
+
+<li><a href="#client_tls_nopeer"> Disabling server certificate verification </a>
+
+<li><a href="#client_tls_per_site"> Per-site TLS policies </a>
+
+<!--
+<li><a href="#client_tls_obs"> Obsolete per-site TLS policy support </a>
+-->
+
+<li><a href="#client_tls_harden"> Closing a DNS loophole with <!-- legacy --> per-site TLS policies </a>
+
+<li><a href="#client_tls_discover"> Discovering servers that support TLS </a>
 
-<li><a href="#client_vrfy_server">Server certificate verification</a>
+<li><a href="#client_vrfy_server">Server certificate verification depth</a>
 
 <li> <a href="#client_cipher">Client-side cipher controls </a>
 
@@ -788,7 +807,7 @@ the overhead of the TLS exchange. </p>
 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
@@ -934,24 +953,19 @@ recommends a maximum of 24 hours.  </p>
 </pre>
 </blockquote>
 
-<h3><a name="client_tls"> Enabling TLS in the Postfix SMTP client </a>
-</h3>
+<h3><a name="client_tls_enable"> Enabling TLS in the Postfix SMTP
+client </a> </h3>
 
 <p> 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. </p>
 
-<p> 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. </p>
-
-<p> 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.  </p>
+<p> 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. </p>
 
 <p> Example: </p>
  
@@ -962,6 +976,9 @@ stays in the queue.  </p>
 </pre>
 </blockquote>
 
+<h3><a name="client_tls_require"> Requiring TLS encryption </a>
+</h3>
+
 <p> 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.  </p>
 
-<p> 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
+<p> 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. </p>
 
-<p> This option is useful only if you know that you will only
+<p> 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.  </p>
 <blockquote>
 <pre>
 /etc/postfix/main.cf:
-    smtp_enforce_tls = no
+    smtp_enforce_tls = yes
 </pre>
 </blockquote>
 
+<h3> <a name="client_tls_nopeer"> Disabling server certificate
+verification </a> </h3>
+
 <p> 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. </p>
 
-<p> Note: the smtp_tls_enforce_peername setting has no effect on
-sessions that are controlled via the smtp_tls_per_site table.  </p>
-
-<p>  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). </p>
+<p>  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.
+</p>
 
 <p> Example: </p>
  
 <blockquote>
 <pre>
 /etc/postfix/main.cf:
-    smtp_tls_enforce_peername = yes
+    smtp_enforce_tls = yes
+    smtp_tls_enforce_peername = no
 </pre>
 </blockquote>
 
-<p> 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. </p>
-
-<p> 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.  </p>
-
-<p> 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. </p>
-
-<p> 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:  </p>
+<h3> <a name="client_tls_per_site"> Per-site TLS policies </a> </h3>
+
+<p> 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. </p>
+
+<!-- insert new-style TLS policy mechanism here
+
+<h3> <a name="client_tls_obs"> Obsolete per-site TLS policy support 
+</a> </h3>
+
+<p> This section describes an obsolete per-site TLS policy mechanism.
+Unlike the newer mechanism it supports TLS policy lookup by server
+hostname, and lacks control over what names can appear in server
+certificates.  Because of this, the obsolete mechanism is vulnerable
+to false DNS hostname information in MX or CNAME records.  These
+attacks can be eliminated only with great difficulty.  </p>
+
+-->
+
+<p> The smtp_tls_per_site table is searched for a policy that matches
+the following information:  </p>
 
 <blockquote>
 
 <dl>
 
-<dt> NONE </dt> <dd> Don't use TLS at all. </dd>
+<dt> remote SMTP server hostname </dt> <dd> 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. </dd>
+
+<dt> next-hop destination </dt> <dd> 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 "<tt>[name]</tt>", <tt>[name]:port</tt>", "<tt>name</tt>" or
+"<tt>name:port</tt>".  </dd>
+
+</dl>
+
+</blockquote>
+
+<p> 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.  </p>
+
+<p> The smtp_tls_per_site table uses a simple "<i>name whitespace
+value</i>" 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:  </p>
 
-<dt> MAY </dt> <dd> Try to use STARTTLS if offered, otherwise use
-the unencrypted connection. </dd>
+<blockquote>
 
-<dt> MUST </dt> <dd> 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. </dd>
+<dl>
 
-<dt> MUST_NOPEERMATCH </dt> <dd> 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. </dd>
+<dt> NONE </dt> <dd> Don't use TLS at all. This overrides a less
+specific <b>MAY</b> 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. </dd>
+
+<dt> MAY </dt> <dd> Try to use TLS if the server announces support,
+otherwise use the unencrypted connection. This has less precedence
+than a more specific result (including <b>NONE</b>) 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".  </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd> 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 <b>NONE</b>
+or a less specific <b>MAY</b> 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.  </dd>
+
+<dt> MUST </dt> <dd> 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 <b>NONE</b>
+and <b>MUST_NOPEERMATCH</b> or a less specific <b>MAY</b> 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.  </dd>
 
 </dl>
 
 </blockquote>
 
-<p> 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:  </p>
+<p> The precedences between global (main.cf) and per-site TLS
+policies can be summarized as follows: </p>
 
 <ul>
 
-<li> <p> If no match was found, the policy is applied as specified
-with smtp_enforce_tls. </p>
+<li> <p> 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". </p>
 
-<li> <p> 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. </p>
+<li> <p> 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).  </p>
+
+<li> <p> After the per-site policy lookups are combined, the result
+generally overrides the global policy. The exception is the less
+specific <b>MAY</b> 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.  </p>
 
 </ul>
 
-<p> 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. </p>
+<h3> <a name="client_tls_harden"> Closing a DNS loophole with 
+<!-- legacy --> per-site TLS policies </a> </h3>
+
+<p> 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: </p>
+
+<ul>
+
+<li> <p> Eliminate MX lookups. Specify local transport(5) table
+entries for sensitive domains with explicit smtp:[<i>mailhost</i>]
+or smtp:[<i>mailhost</i>]:<i>port</i> destinations (you can assure
+security of this table unlike DNS); in the smtp_tls_per_site table
+specify the value <b>MUST</b> for the key [<i>mailhost</i>] or
+smtp:[<i>mailhost</i>]:<i>port</i>. 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. </p>
+
+<li> <p> 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.  </p>
+
+</ul>
 
 <p> Example: </p>
-<blockquote>
-<pre>
+
+<blockquote> <pre>
 /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
 </pre>
 </blockquote>
 
+<h3> <a name="client_tls_discover"> Discovering servers that support
+TLS </a> </h3>
+
 <p> 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. </p>
@@ -1123,7 +1235,7 @@ postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
 </pre>
 </blockquote>
 
-<h3><a name="client_vrfy_server">Server certificate verification</a> </h3>
+<h3><a name="client_vrfy_server">Server certificate verification depth</a> </h3>
 
 <p> 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. </p>
 </blockquote>
 
 <li> <p> Configure Postfix, by adding the following to
-<tt>/etc/postfix/main.cf</tt>. </p>
+<tt>/etc/postfix/main.cf </tt>. </p>
 
 <blockquote>
 <pre>
@@ -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. </p>
 
+<li> <p> smtp_tls_per_site: the MUST_NOPEERMATCH per-site policy
+cannot override the global "smtp_tls_enforce_peername = yes" setting.
+</p>
+
+<li> <p> 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".
+</p>
+
 </ul>
 
+<p> The smtp_tls_per_site limitations were removed by the end of
+the Postfix 2.2 support cycle. </p>
+
 <h2><a name="credits">Credits </a> </h2>
 
 <ul>
@@ -1459,6 +1585,10 @@ J&auml;nicke at Cottbus Technical University.
 <li> Wietse Venema adopted the code, did some restructuring, and
 compiled this part of the documentation from Lutz's documents.
 
+<li> 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.
+
 </ul>
 
 </body>
index e4ac74bfbc80bae7557aaca66af0f4e570394459..e9502a3aeba6ae4657ed4f19bf89a7bc24f20b4a 100644 (file)
@@ -4688,9 +4688,11 @@ a restriction list, to make the default policy explicit.</dd>
 <dt><b><a name="reject_multi_recipient_bounce">reject_multi_recipient_bounce</a></b></dt>
 
 <dd>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. <br> 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.
+<br> 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. </dd>
 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. </dd>
 
@@ -6508,7 +6510,8 @@ This feature is available in Postfix 1.1 and later.
 %PARAM defer_service_name defer
 
 <p>
-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.
 </p>
 
@@ -7550,7 +7553,8 @@ Obsolete SUN mailtool compatibility feature. Instead, use
 %PARAM trace_service_name trace
 
 <p>
-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 "<b>sendmail -v</b>".
 </p>
@@ -8512,71 +8516,77 @@ CommonName of this attacker will be logged). </p>
 %PARAM smtp_tls_per_site
 
 <p> Optional lookup tables with the Postfix SMTP client TLS usage
-policy by next-hop domain name and by remote SMTP server hostname.
-</p>
-
-<p> 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:  </p>
+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).  </p>
+
+<p> 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:  </p>
 
 <dl>
 
-<dt> NONE </dt> <dd>Don't use TLS at all. </dd>
-
-<dt> MAY </dt> <dd>Try to use STARTTLS if offered, otherwise use
-the unencrypted connection. </dd>
-
-<dt> MUST </dt> <dd>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. </dd>
-
-<dt> MUST_NOPEERMATCH </dt> <dd>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. </dd>
+<dt> NONE </dt> <dd> Don't use TLS at all. This overrides a less
+specific <b>MAY</b> 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. </dd>
+
+<dt> MAY </dt> <dd> Try to use TLS if the server announces support,
+otherwise use the unencrypted connection. This has less precedence
+than a more specific result (including <b>NONE</b>) 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".  </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd> 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 <b>NONE</b>
+or a less specific <b>MAY</b> 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.  </dd>
+
+<dt> MUST </dt> <dd> 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 <b>NONE</b>
+and <b>MUST_NOPEERMATCH</b> or a less specific <b>MAY</b> 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.  </dd>
 
 </dl>
 
-<p> Special hints for enforcement mode:  since no secure DNS lookup
-mechanism is available, the recommended setup is:  </p>
-
-<dl>
-
-<dt> Postfix 2.2.9 </dt>
-
-<dd> <ul>
-
-<li> Specify "smtp_cname_overrides_servername = no". This avoids
-false hostname information in DNS CNAME records that could bypass
-a hostname-based TLS usage policy.
+<p> 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: </p>
 
-<li> 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.
-
-<li> Specify MUST for these mail hosts in the smtp_tls_per_site
-table.
-
-</ul> </dd>
-
-<dt> Postfix &lt; 2.2.9 </dt>
-
-<dd> <ul>
+<ul>
 
-<li> 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.
+<li> 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.
 
-<li> Specify MUST for these mail hosts in the smtp_tls_per_site
-table.
+<li> 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.
 
-</ul> </dd>
+<li> Specify MUST for these mail hosts (including [ ] and port) in
+the smtp_tls_per_site table.
 
-</dl>
+</ul>
 
 <p> </p>
 
@@ -9142,7 +9152,7 @@ configuration file or rendez-vous point. </p>
 
 <p> This feature is available in Postfix 2.3 and later. </p>
 
-%PARAM plaintext_session_reject_code 450
+%PARAM plaintext_reject_code 450
 
 <p>
 The numerical Postfix SMTP server response code when a request
index d9e70e59d75ecffbea4482cba4e8c0e8094be918..f03d4417738b283cb692e2317fd65b3c4c7daf6a 100644 (file)
@@ -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;
            }
index c7a824ca5dec327fd01f32a07277e12ebac94c13..1b64722b7508788b50aea4e49c6edd92e9fc0091 100644 (file)
@@ -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);
 
index 5fbb28dbfc1bd37d48a57533f0364a7a55345960..bc3ea6d770ac3d81ee605f66085e0a1110219007 100644 (file)
@@ -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);
index 22f6e5094b4a8d4a2ae445cb8bfacbbab4b7043f..797609778b50f14df0678857599af4e0e7ed3e6a 100644 (file)
@@ -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();
 }
index ffdf81a4189ab0c032f0ab420ee82b0b2df972a9..ce98ec8b47b7746b2698a4cbc924daedf96fa9e5 100644 (file)
@@ -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)
index 1a6faf28230c56952e4d12845e7350b27adf2d29..cb9441562921c20e146b46c345a45ac6c1a09c77 100644 (file)
@@ -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.in hash:virtual8_map >virtual8.tmp
-       diff virtual8.ref virtual8.tmp
-       rm -f virtual8.tmp virtual8_map.db
-
 xtext_test: xtext
        ./xtext <xtext.c | od -cb >xtext.tmp
        od -cb <xtext.c >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
index 3b95f97688ccac492aa932b1bdf0cd4677d181f8..f7d2dcad3998f96c5c88ef33a796a5cdaa503bb9 100644 (file)
@@ -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);
index a0117cdc771aea51fd2e38faa90fdf024e45ea56..02ecac2f9c9a99900935aa3396f45a366a696d59 100644 (file)
@@ -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)
index 440e4ebcf9233ecf04c6825f63c131912afca6cd..54a3059cf04e6e39c1f89c2ed73f57853af187ab 100644 (file)
@@ -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
index 0f0a57b988b83d868de1d48ad0e86311e4d48f9c..d98bf6f33729a715d2b63b62c38b931f7b471b25 100644 (file)
@@ -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 {
index 8938e6a884c5e2adf746daf8648c786034c95ccf..23abc30d334578f5e0ef93f00c911c740bbdf711 100644 (file)
@@ -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);
index 029d2fdeff85c0e743e7446ff5082e6536477781..5c6e546dde97851a64c29dbd2c88e98045d1c312 100644 (file)
@@ -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);
index eaaad4908df53bb9d12837751ff39dfff365b2c8..27f9bd603190fd9284a591150a3012d2a787141b 100644 (file)
@@ -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);
index 282366c6ce30cb3cc700bc2f26eb65884a740f71..0e82eaa0fc1d4d82d454bc5501ea860018fd4420 100644 (file)
 #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);
 }
 
index 976168eba7079373346aae1b1bc8b60523348bdc..acaf6e7861b0d583c5993c63edf12daa36463dc9 100644 (file)
 #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);
 }
 
index f4eea08bde579cd40821b43449e6fc30ce5ef0a9..5ce496af76d2845c6e9be213dae578b3a142c9e9 100644 (file)
@@ -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",
index 83d36a87cc0d8a3955ee652a60978e344b4a862c..251f6f6ac0b0b255beaa5b29b2248f4108c25407 100644 (file)
@@ -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));
 }
index 4c6dab3557e54ea307c728e65062159b8d4cbd2c..e865ab65c27e7b9f8c6a3c587ed22a3aad7a0e02 100644 (file)
@@ -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
index cda022b043e4e3c99eb0f4eed60f33f89a4024f6..1ebbbc20b0dcf38b241cd15af00adb18481c18f9 100644 (file)
@@ -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);
index ad0c6c39423856acd94459ed74d2a36bc47d76b3..c8a6e2c9fb216403f2e105f1c6fcde3be1ff7673 100644 (file)
@@ -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, "+");
index fc1c56c9efe8aab7b5bfb9d86c0b155dbbf33fba..db436097252969f4aa9e88bcac67a8e50c410647 100644 (file)
@@ -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);
index e7e43e1ff5aa67381991887eb401ce03f32a32fd..ce4ad033f2c7f8e02736deed2da8a1709cd809fe 100644 (file)
@@ -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;
 
index f77b11e485b163aef403f3e62fb5506411d9a814..eb592a07d241441f8ff64e3ef2f47b240f99caae 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20060112"
+#define MAIL_RELEASE_DATE      "20060123"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index ad97ee6d61be9185c55516562ad7c5d9139a8ad8..d1c705b91bf9ad8ade0c152bbad119a133d35536 100644 (file)
 /*     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
 /* .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)
index e1c46796dd661e700b6b0296243de866daa9cd07..ec53be5efa7581fbaed72ff8a1f16510e3a4615e 100644 (file)
@@ -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;
     }
index cfb1b41784a77fde66499950e8bfeb2a893a9ee7..3c8edddaddbe9d1cdfa0c17126a165cf8eb567f4 100644 (file)
@@ -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);
 }
index 1c3b723f887d40081362896589118e15e8132d03..985f42c3275124b8d32786756d014db44e529032 100644 (file)
@@ -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);
 }
index fcaf2c6240123c856acda2e4eba9ca4512003ae7..50c95a783f59722647a48b012472a6a2eb70ec6c 100644 (file)
@@ -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",
index 7aaa756880a42b9de82c6a9662db712db6b862dd..601f7ca000fa73aeacaee31a2d51d166d1976f03 100644 (file)
@@ -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))
index c1d3a058b7461478152ce2315cc5447abb2cea95..10573e7df1d88b1e4bc17f087c7a7fbc9222f06f 100644 (file)
@@ -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) {
index d6d30a09802babb95addb0896ef948f6eda45f0c..e6e86ee06f7e3bc8e39e49ea9486242614cc7693 100644 (file)
@@ -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 {
index 14dd3cd5e0ae70ad24af78ddfd5361eba44f0993..916cce3fc876d00179cb0fbb7870feeeb6ad0453 100644 (file)
@@ -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 (file)
index d030a94..0000000
+++ /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 (file)
index 0e9c19c..0000000
+++ /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 (file)
index f0231d5..0000000
+++ /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 (file)
index fb05dc7..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*++
-/* NAME
-/*     virtual8_maps 3
-/* SUMMARY
-/*     virtual delivery agent map lookups
-/* SYNOPSIS
-/*     #include <virtual8_maps.h>
-/*
-/*     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 <sys_defs.h>
-#include <string.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <mymalloc.h>
-
-/* Global library. */
-
-#include <maps.h>
-#include <mail_params.h>
-#include <strip_addr.h>
-#include <virtual8_maps.h>
-
-/* 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 <vstream.h>
-#include <vstring.h>
-#include <vstring_vstream.h>
-
-#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 (file)
index 67c5df9..0000000
+++ /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 <virtual8_maps.h>
-/* DESCRIPTION
-/* .nf
-
- /*
-  * Global library.
-  */
-#include <maps.h>
-
- /*
-  * 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
index 9ab147b2754698822d1aee2a11edcabb416eb7cf..4674b7e0b66ea193351272341e7e4512c6511f23 100644 (file)
@@ -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;
 
index 759f71c34ddb403cb40bbea43c580753eb25ba60..ce793369a35ffa973c0ef2c1d41bf4ef2ab33dc4 100644 (file)
@@ -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();
 }
index fc2119a6960ee55d12f7dc83445f8fc6c3d651cc..4b754caa70fe1757c001c62f9e3b101d97eef63e 100644 (file)
@@ -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);
index c6d7ed9f0795160bda0dc442ac147a3cdf441a04..4293c2f92a5e71b1662e033869002cb255e41cc9 100644 (file)
@@ -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));
     }
index d361b2c55b104ed16eb5e9c854290b181c93aec8..fd1ed845962cdb145455b0769a8fd4e45a8f745b 100644 (file)
@@ -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)
index 6cfefa16cb1bdad653e6618de1f68541c4ea25a8..bb01bce4834ce6bbdd994a9b9a86f5dfec1748b2 100644 (file)
@@ -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)
index b7e672429718b78d6f4bb3fc8b827db82d5ba444..9f686add49a3a1f70b276a4a847e670aacb81405 100644 (file)
@@ -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)
index 1f813ce4d482b108bfe3ab82953a1149a0e6c15c..356c844d480ef1e92603d9aaf41cd31732d2805c 100644 (file)
@@ -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);
index 0a73ec66f90d89529f872f02d72c9c3de7fa7644..e6fcb5c507c489ece1da938653c15a6d59664059 100644 (file)
@@ -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 {
index 2fa055b111330a6c05882bd437b3172ffdfb2df6..a62d065f020507464c70648757f9aa494f7c078d 100644 (file)
 /*     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);
        }
index 461369cc27e52fa7ae6e359281d89dc55e16869d..488753f60c7012c0886c3520a993f531d3068887 100644 (file)
@@ -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);
index ef6ebcda65470687aa2bcbf691d375145cc8bef2..bc9e2bd8fc7c25dae9e5a2c6c69e02b60f122f18 100644 (file)
 /*     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);
        }
index 49bc5f5f5b782c9b5518cbaeef530f5f96a78fc8..8b331ecc104639cb4daa905a6371e33be592e4bf 100644 (file)
@@ -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
index 44b377bad9a4e3b82e5850aad3eef3e36041c3c0..9bfd2a2657715f17d340c159a0f749075ecba3d5 100644 (file)
 #include <smtp_stream.h>
 #include <user_acl.h>
 #include <valid_mailhost_addr.h>
+#include <mail_dict.h>
 
 /* Application-specific. */
 
index e1ffd7e54f47b61de7a550fbd91f6e9dcf2fd3c6..7b9326a55597db079a261ea89e65351b2d91ead4 100644 (file)
@@ -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);
        }
     }
index 9dc54c2f58815b8783e1483d68bd14b7428faa54..59ae7f1027506fd95c21189db39cd797a87909e4 100644 (file)
@@ -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);
index bb8a5ab4ff0aa765d57f4681b28f690281b426cf..ee45281bcbba510fa8144d1dec2e6ac27b8212cf 100644 (file)
@@ -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);
index 86e17f45913b0de5f3e69b09efb4dad93d454cb8..9d2b0dbb7b924f93035730ed9dca8d2a36df735f 100644 (file)
@@ -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);
            }
        }
index 88a5b68076267c9a9400f908ce84ae4280f3401b..3bf1a67e443c7d5bdeee7f1d5c1455b917bf6761 100644 (file)
@@ -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
 /* .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
index 668daea677727181e4b922f4adcdeffe18da3c35..1ad8c36908a8829ccad4d2896af020dc52b23a4f 100644 (file)
@@ -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 (file)
index 0000000..867d02c
--- /dev/null
@@ -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 <sys_defs.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <vstring_vstream.h>
+#include <stringops.h>
+
+ /*
+  * 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 (file)
index 0000000..e0baa46
--- /dev/null
@@ -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 <sys_defs.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <vstring_vstream.h>
+#include <stringops.h>
+
+ /*
+  * Application-specific.
+  */
+#include <smtp.h>
+
+ /*
+  * 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);
+}
index a05bc8ae2e462ef28d1a10c5982bf0d8dc9aeb8c..ee00bb0ac28984152c333b560fc93a20287172d9 100644 (file)
@@ -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 */
index e79832fb0866a26af6bd4512220c29b0dd46c983..4ec7dc55a68908bfb9aa3b56006cd9cc11985a37 100644 (file)
@@ -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
 
index bb9f0d147cb24e6daa8eda6c9ac4682943e87504..406b2aa1f70bf84b474d14f6c087fdf68c287852 100644 (file)
@@ -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
index 8142cc47a3c29266ef70189f50554e46769e1533..495c544a765c6496ae6aea0776a537043066459d 100644 (file)
@@ -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.
 /*
index 297dee8a03287d8ef04536e7bcf082c781ec0ea6..23b2937e056e9f79581c5fe50daa18ac526ed237 100644 (file)
@@ -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);
index 5cee7ff284e90a250d6d726a3bde88573da3113d..1dcdf269daf41cdbbe0e3124bde80f8c9d3bd81f 100644 (file)
@@ -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,
index 38e78ddccb4cd7ad452867511dd18dd650d4fa31..facf547e396e1980d03e524170f693d6208e1a36 100644 (file)
@@ -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");
index ccdb8fdef738f96156df0a168f7dd57f70933536..0807675994c265bb184fce033f92fb01a67f5506 100644 (file)
 
 #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_policy_print - printpolicy level */
+
+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_site_policy - look up per-site TLS policy */
+/* smtp_tls_policy_lookup - look up per-site TLS security 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_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;
+    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);
+       }
+    }
+}
+
+/* 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;
 
     /*
-     * Look up a non-default policy.
+     * 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.
      */
-    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
-           msg_warn("Table %s: ignoring unknown TLS policy '%s' for %s %s",
-                    var_smtp_tls_per_site, lookup, site_class, site_name);
+    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);
     }
-    myfree(lookup_key);
+
+    /*
+     * 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 (file)
index 0000000..95c295b
--- /dev/null
@@ -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 (file)
index 0000000..5b9f187
--- /dev/null
@@ -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
index 2776c4c91923c7bc5b81abf8ba46df33e13f3cfd..39cac5bd03fd0c2f62e99ce9c0772ae89e39079a 100644 (file)
@@ -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
index 664f3ddd81302e6affd0a22733a5f17aa812ccf5..a09cf0c94c930212e6a2dbca5c1aef703ab62320 100644 (file)
@@ -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,
 };
 
index f1d9af340674c6a6b0121e95709e6a90976dbead..ebde037d023cb8a345a0fe4d405592a31b51d393 100644 (file)
@@ -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
index 9cf948c3fb9fd12c1086cbc7ba2e9aacdbbb3801..2caa81af4b09b3722332847895ece433c91f0ae1 100644 (file)
 #include <mail_addr_find.h>
 #include <match_parent_style.h>
 #include <strip_addr.h>
-#include <virtual8_maps.h>
 #include <cleanup_user.h>
 #include <record.h>
 #include <rec_type.h>
@@ -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;
            }
index 073468b23375c06ec3eb341580fbab6198257f29..7dcd497287942cff29f229d187f39cb47e0b1498 100644 (file)
@@ -49,11 +49,11 @@ OK
 >>> client foo 123.123.123.123
 OK
 >>> helo foo.
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.1.0 <foo.>: Helo command rejected: Host not found; proto=SMTP helo=<foo.>
-450 4.1.0 <foo.>: Helo command rejected: Host not found
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.7.1 <foo.>: Helo command rejected: Host not found; proto=SMTP helo=<foo.>
+450 4.7.1 <foo.>: Helo command rejected: Host not found
 >>> helo foo
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.1.0 <foo>: Helo command rejected: Host not found; proto=SMTP helo=<foo>
-450 4.1.0 <foo>: Helo command rejected: Host not found
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.7.1 <foo>: Helo command rejected: Host not found; proto=SMTP helo=<foo>
+450 4.7.1 <foo>: Helo command rejected: Host not found
 >>> helo spike.porcupine.org
 ./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 5.7.1 <spike.porcupine.org>: Helo command rejected: name server spike.porcupine.org; proto=SMTP helo=<spike.porcupine.org>
 554 5.7.1 <spike.porcupine.org>: 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: <queue id>: 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: <queue id>: 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 [::]
index df0c2174a332805491e53f7b2750d77b3c851015..0553750acbf77be5edf5ceaa582f033d14e72a42 100644 (file)
@@ -49,11 +49,11 @@ OK
 >>> client foo 123.123.123.123
 OK
 >>> helo foo.
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.1.0 <foo.>: Helo command rejected: Host not found; proto=SMTP helo=<foo.>
-450 4.1.0 <foo.>: Helo command rejected: Host not found
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.7.1 <foo.>: Helo command rejected: Host not found; proto=SMTP helo=<foo.>
+450 4.7.1 <foo.>: Helo command rejected: Host not found
 >>> helo foo
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.1.0 <foo>: Helo command rejected: Host not found; proto=SMTP helo=<foo>
-450 4.1.0 <foo>: Helo command rejected: Host not found
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.7.1 <foo>: Helo command rejected: Host not found; proto=SMTP helo=<foo>
+450 4.7.1 <foo>: Helo command rejected: Host not found
 >>> helo spike.porcupine.org
 ./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 5.7.1 <spike.porcupine.org>: Helo command rejected: name server spike.porcupine.org; proto=SMTP helo=<spike.porcupine.org>
 554 5.7.1 <spike.porcupine.org>: Helo command rejected: name server spike.porcupine.org
index 25afca7c05056db27738c1182c01920df3f35f15..87b1bb9e90c5b3752872720e397c6be7b5542b96 100644 (file)
@@ -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: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.1_dsn>: Sender address rejected: reject; from=<user@4.1.1_dsn> proto=SMTP helo=<4.4.0_dsn>
-554 5.1.0 <user@4.1.1_dsn>: Sender address rejected: reject
+./smtpd_check: mapping DSN status 4.1.1 into Sender address status 4.1.7
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.1_dsn>: Sender address rejected: reject; from=<user@4.1.1_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.7 <user@4.1.1_dsn>: 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: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.8 <user@4.1.2_dsn>: Sender address rejected: reject; from=<user@4.1.2_dsn> proto=SMTP helo=<4.4.0_dsn>
@@ -107,17 +107,17 @@ OK
 ./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.3_dsn>: Sender address rejected: reject; from=<user@4.1.3_dsn> proto=SMTP helo=<4.4.0_dsn>
 554 5.1.7 <user@4.1.3_dsn>: 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: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.4_dsn>: Sender address rejected: reject; from=<user@4.1.4_dsn> proto=SMTP helo=<4.4.0_dsn>
-554 5.1.0 <user@4.1.4_dsn>: Sender address rejected: reject
+./smtpd_check: mapping DSN status 4.1.4 into Sender address status 4.1.7
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.4_dsn>: Sender address rejected: reject; from=<user@4.1.4_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.7 <user@4.1.4_dsn>: 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: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.5_dsn>: Sender address rejected: reject; from=<user@4.1.5_dsn> proto=SMTP helo=<4.4.0_dsn>
 554 5.1.0 <user@4.1.5_dsn>: 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: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.6_dsn>: Sender address rejected: reject; from=<user@4.1.6_dsn> proto=SMTP helo=<4.4.0_dsn>
-554 5.1.0 <user@4.1.6_dsn>: Sender address rejected: reject
+./smtpd_check: mapping DSN status 4.1.6 into Sender address status 4.1.7
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.6_dsn>: Sender address rejected: reject; from=<user@4.1.6_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.7 <user@4.1.6_dsn>: Sender address rejected: reject
 >>> mail user@4.1.7_dsn
 ./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.7_dsn>: Sender address rejected: reject; from=<user@4.1.7_dsn> proto=SMTP helo=<4.4.0_dsn>
 554 5.1.7 <user@4.1.7_dsn>: Sender address rejected: reject
index bf37f9c3351476c9218bc1b83ef5fc6a4cb43263..d436967282bb19ebb98a3b9d5884e9110fc10712 100644 (file)
@@ -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 */
index fa9a4450f166c38b7f665326d24458f2589aa838..a3a42dff5cb50f9cae5d59aa75a7148d244f3820 100644 (file)
 #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
index f79a8f265d19714a2ab3ceb602f73f8e49ddd234..8295ce99cadd081d4ce07e53de1fffc2715e44a6 100644 (file)
@@ -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
index 0e1cdf93cb2580e85173314acb0e2650f2b95ad0..c493775c0165becc9dbb72cd836967ae319152ee 100644 (file)
@@ -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);
index 91a85ed6f32601b7bafbf968f65213ab71efad77..042ee298405ba5e99e29ef7eef99888baea4a47d 100644 (file)
@@ -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);
 }
 
index 5651523977761dad273dc0c4c01ab797c29f2db7..e086e2c311bcc59e7fbde76c640409665f6c4b67 100644 (file)
@@ -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);
index f961b011169260e3b49a62995805d080d6bcaa8f..b72619957254110ad17cf607c5dd512a097e10d2 100644 (file)
@@ -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);
 }
index c1a275f994ce181ae4f46feebfc15838da170281..ac0ffbadfb429158e71b7db4ac2a67839cffcb88 100644 (file)
@@ -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);
 
index db6bc26c90b90235b47895d5264e19329b46d17d..8905177461866e57db678c2623d1bf13b066427e 100644 (file)
@@ -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);
 }
index 9852dea32ba56df94f4c729cc81f50f37f002516..cdcd6dba8f9b9ec9e73b4ce63f334bbb130fe9ee 100644 (file)
@@ -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 */
index 8e3cb4e08bd795af6499d14b0c0acd12a219b657..cb1b23c1464fb3b04ad39e302809839396123c76 100644 (file)
@@ -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
index 47f7576353a0719a176c1a02f19508dbcead439c..cdaeb79a91074ff8a943fc5ef81428e0bda57bef 100644 (file)
@@ -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"
index 87aac757478ccda3eed5d521f05ec14999bd5d37..ea601b704b8f6e67f167ce8b37214325763add4a 100644 (file)
@@ -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 */
index 04222e459b2f4ca04a37764de6368d0a968ec9a1..3393886056fb38aa0ba2d03a25aa5545af5edbd2 100644 (file)
@@ -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",
index 46aaa7631d91258b51f6faceab0036232ff9c2c4..f9cd51e0a5ecef706515ace0bd9943b7a34f10a1 100644 (file)
@@ -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",
index aea66b5c48a30b6062ef039b1b878ae9b85043cf..61106f7e305be22738870af69f6531500e241cb5 100644 (file)
@@ -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",
index db1f1fa0088c4ab2b51a4d334efee8eb809f2b86..8297e7a18683b4f573334f0de151c9993ed0f17f 100644 (file)
@@ -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));
index 2d5b6936faff0e0b3a53dd5aae4450ee577226f9..d148e6d8ffa34521a43ca67ba90eed586e6c02aa 100644 (file)
@@ -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);
 
index 70f216e6a7376475c667b3ae112c24abe66b2941..2d8f1a2881bf3c8b52dddc0ff21d2aa469b042b6 100644 (file)
@@ -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);
 
index c608c6c283ec6783deff8360fc08ff149c87c212..626531cc09a208ef82a8960c6cd8bf5c8cad5fd8 100644 (file)
@@ -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)
index 458c5f9371d8d226c5e237075787ad817183483f..a168c1adc3a0f3cdff4108a60d1313592b97a6c6 100644 (file)
@@ -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
index e57df6506cfe9bd9b5cd305b3023ad36804a7701..b39a97154a5507f84a280b652990f7357b7db237 100644 (file)
@@ -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
 /*
 /*     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
 #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));
+}
index 9532fec0befc3f4132b5434341037ac195681f94..eadc7733fd99425e87ccec1db52fa621a325454a 100644 (file)
@@ -21,6 +21,7 @@
   */
 #include <vstream.h>
 #include <argv.h>
+#include <vstring.h>
 
  /*
   * 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
index 5d9dc83a68d850894f14159b625158e9b5918ff9..9c08a90716ba355fcf89faf0899fc2d87590e504 100644 (file)
@@ -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;
 }
 
index 6d8d11c8d755ab366fc32f096b082e734c1cf29b..1aa67a3fd423b91c8b77adcc6ac0929fa2ba2a9d 100644 (file)
@@ -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);
 }
index 586cb424710e48565290ea8d22a331ef33979aeb..24142fcde167fdef0fe9ddaef222c6ac0429861d 100644 (file)
@@ -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;
index 87e527694368394a87f29d268168eaebc990334d..29489946bf7dc10fb0cbb91834eb6af9664ca2a3 100644 (file)
@@ -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;
index e87ac15a93d60a0d605820e96f52479d01fd658d..eb5b6a58267b0985c4800806f3ec53a0b9c1e5f1 100644 (file)
 #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));
 }
index c6497f8888c049437a51249a43468a5c03296696..c0cbd12fb98caef5ee4a6371d73acc94adb0fc3d 100644 (file)
@@ -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));
 }
index 104fa8f14e6cc3b3701eba2e6c4bf5c99d895f96..da61f07afd77cc01d6f110feb7e442a87843de11 100644 (file)
@@ -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));
index 2f1a45772ce439f649ec6875e2866863ce52a118..87163ac2cff1deef10f514f787508293dd1209b6 100644 (file)
@@ -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
index c89911f54020f1eca47290a361bb9956cbea05b0..e52c8725590e7f61eb57a05a56dfe086a0462d21 100644 (file)
 /* .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);
index c706f522f5afff87b0728a49a1e633cde7bc9e70..8a4d9ae628351a6691606a1e0334104bc89e253e 100644 (file)
@@ -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;
 
index f56a7ea595b55687d80c9ae9e9670032a26a6c26..b0f1d9768cc750de49c120d128b33bc5198c87a9 100644 (file)
@@ -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;
index 35ee7782ec9bd0138a46c49766958c4dd2365d52..8c6085d648e60510c26549ac17c9f8f2441770c4 100644 (file)
@@ -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;
index 2da83feb56c9f50750ed0438b9906a797dad1365..1e8d2bc103651c0691a30bd11fc43542e7a74da4 100644 (file)
@@ -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));
 }
index 60c776d50e6ac6b0aeb491ef525d365fca5e14fc..ed50c191557eec7bc1afa3034b0394050f8b23b2 100644 (file)
@@ -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));
 }
index e113e6a4c8b111b99f35351f824f593e9d79c7d9..86116e1e0541ede93568573029ed4bc3ed587262 100644 (file)
@@ -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);
 }
 
index fb57b3e1d66b375301a7f1aec0a9b0c36b648c71..f8c60eefa3f5beb280300cea4000d2c5837ba277 100644 (file)
@@ -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,
index 29eff7e1c45a21b025d98895c09d251eceb85cc0..3f9f20eea002c0763721065bdefc06c13bb359b0 100644 (file)
@@ -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);
     }
 
index 49d6ed2e08e8643244f508a27108fc0846c5400e..bc736010136b8d1060138fbe202aaef550f0d6e7 100644 (file)
@@ -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 ===
index 8a2a361ee05dd1f2c0067fcfbd924726ec8d5e55..d049b9ec2dd6d7c5f4c77be49689b3c1d1dad86a 100644 (file)
@@ -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);
index 3da7ac27a3b015227a1aa8a7c152eacfbbbf6666..423bfae6a61326677910f8daa5e5b61ac20c3f25 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * Utility library.
+  */
+#include <vstring.h>
+
  /*
   * 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
index 27d9d849fb24a4e22a8dcb3c959256d8bc606296..025df56746087a0698592222974d471db2c2de71 100644 (file)
@@ -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) {
index ecc0d5f39d49ed0429d1738079d47dc07fcd6a0b..49fccbcb11f1f0f53d9040608fc0596fe2a93bc3 100644 (file)
@@ -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);
        }
     }
index fd5df201dc8d816c8cba8c657465a7a293f8b80b..0d636796e95dbf9b3ed02cd0ae6c81b5068912d4 100644 (file)
 /*     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);
index 2a2d51c0b58b0dea14d5aa49f2b905b2e9449706..ac9d8f3ac296fb371290dddc7bfc83b7514c9760 100644 (file)
@@ -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