From 3e160e27e4686620d16477a9ea9cf00141e52ce7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 10:41:51 +0200 Subject: Adding upstream version 3.9.0. Signed-off-by: Daniel Baumann --- .indent.pro | 3 + HISTORY | 777 ++++++++++++++++++++-- INSTALL | 44 +- Makefile.in | 9 +- README_FILES/AAAREADME | 2 + README_FILES/ADDRESS_CLASS_README | 76 ++- README_FILES/ADDRESS_REWRITING_README | 223 ++++--- README_FILES/COMPATIBILITY_README | 64 +- README_FILES/DATABASE_README | 5 +- README_FILES/DEPRECATION_README | 270 ++++++++ README_FILES/INSTALL | 44 +- README_FILES/LOCAL_RECIPIENT_README | 2 +- README_FILES/MAILLOG_README | 10 + README_FILES/MILTER_README | 6 +- README_FILES/MONGODB_README | 188 ++++++ README_FILES/POSTSCREEN_README | 4 +- README_FILES/TLS_README | 120 ++-- RELEASE_NOTES | 334 ++++++---- RELEASE_NOTES-3.8 | 128 ++++ WISHLIST | 29 +- conf/access | 4 +- conf/aliases | 162 ++--- conf/canonical | 49 +- conf/dynamicmaps.cf | 1 + conf/generic | 10 +- conf/header_checks | 66 +- conf/main.cf | 4 +- conf/post-install | 28 +- conf/postfix-files | 7 + conf/postfix-script | 21 +- conf/relocated | 10 +- conf/virtual | 202 +++--- html/ADDRESS_CLASS_README.html | 83 ++- html/ADDRESS_REWRITING_README.html | 159 +++-- html/COMPATIBILITY_README.html | 96 +-- html/DATABASE_README.html | 9 +- html/DEPRECATION_README.html | 411 ++++++++++++ html/INSTALL.html | 3 + html/LOCAL_RECIPIENT_README.html | 3 +- html/MAILLOG_README.html | 10 + html/MILTER_README.html | 2 +- html/MONGODB_README.html | 263 ++++++++ html/Makefile.in | 6 +- html/POSTSCREEN_README.html | 4 +- html/TLS_README.html | 164 +++-- html/access.5.html | 4 +- html/aliases.5.html | 14 +- html/canonical.5.html | 30 +- html/cleanup.8.html | 98 +-- html/dnsblog.8.html | 4 +- html/generic.5.html | 17 +- html/header_checks.5.html | 59 +- html/index.html | 4 + html/lmtp.8.html | 248 +++---- html/local.8.html | 234 +++---- html/mailq.1.html | 8 +- html/makedefs.1.html | 6 +- html/master.5.html | 13 +- html/master.8.html | 8 +- html/mongodb_table.5.html | 215 ++++++ html/mysql_table.5.html | 188 +++--- html/newaliases.1.html | 8 +- html/pcre_table.5.html | 8 +- html/pgsql_table.5.html | 13 + html/pipe.8.html | 106 +-- html/postcat.1.html | 2 +- html/postconf.1.html | 170 ++--- html/postconf.5.html | 771 ++++++++++++++++----- html/postdrop.1.html | 2 +- html/postfix-manuals.html | 6 +- html/postfix.1.html | 5 +- html/postkick.1.html | 2 +- html/postlock.1.html | 2 +- html/postlog.1.html | 7 + html/postlogd.8.html | 13 +- html/postscreen.8.html | 32 +- html/postsuper.1.html | 2 +- html/posttls-finger.1.html | 12 +- html/proxymap.8.html | 2 +- html/qmgr.8.html | 4 +- html/qmqpd.8.html | 2 +- html/regexp_table.5.html | 8 +- html/relocated.5.html | 9 +- html/sendmail.1.html | 8 +- html/smtp-source.1.html | 43 +- html/smtp.8.html | 248 +++---- html/smtpd.8.html | 298 +++++---- html/socketmap_table.5.html | 2 +- html/tlsproxy.8.html | 111 ++-- html/trivial-rewrite.8.html | 21 +- html/virtual.5.html | 159 ++--- makedefs | 6 +- man/Makefile.in | 7 +- man/man1/makedefs.1 | 1 + man/man1/postcat.1 | 2 +- man/man1/postconf.1 | 17 +- man/man1/postdrop.1 | 2 +- man/man1/postfix.1 | 3 +- man/man1/postkick.1 | 2 +- man/man1/postlock.1 | 2 +- man/man1/postlog.1 | 6 + man/man1/postsuper.1 | 6 +- man/man1/posttls-finger.1 | 11 +- man/man1/sendmail.1 | 7 +- man/man1/smtp-source.1 | 42 +- man/man5/access.5 | 4 +- man/man5/aliases.5 | 14 +- man/man5/canonical.5 | 22 +- man/man5/generic.5 | 6 +- man/man5/header_checks.5 | 46 +- man/man5/master.5 | 12 +- man/man5/mongodb_table.5 | 259 ++++++++ man/man5/mysql_table.5 | 18 + man/man5/pcre_table.5 | 11 +- man/man5/pgsql_table.5 | 11 + man/man5/postconf.5 | 719 +++++++++++++++----- man/man5/regexp_table.5 | 11 +- man/man5/relocated.5 | 6 +- man/man5/socketmap_table.5 | 2 +- man/man5/virtual.5 | 22 +- man/man8/cleanup.8 | 24 +- man/man8/dnsblog.8 | 3 +- man/man8/local.8 | 31 +- man/man8/master.8 | 8 +- man/man8/pipe.8 | 5 + man/man8/postlogd.8 | 14 +- man/man8/postscreen.8 | 32 +- man/man8/proxymap.8 | 2 +- man/man8/qmgr.8 | 2 +- man/man8/qmqpd.8 | 2 +- man/man8/smtp.8 | 99 +-- man/man8/smtpd.8 | 21 +- man/man8/tlsproxy.8 | 6 + man/man8/trivial-rewrite.8 | 17 +- mantools/check-see-postconf-d-output | 6 + mantools/check-snapshot-nonprod | 13 + mantools/dehtml | 6 +- mantools/postlink | 12 + postfix-install | 9 +- proto/ADDRESS_CLASS_README.html | 83 ++- proto/ADDRESS_REWRITING_README.html | 157 +++-- proto/COMPATIBILITY_README.html | 96 +-- proto/DATABASE_README.html | 7 +- proto/DEPRECATION_README.html | 411 ++++++++++++ proto/INSTALL.html | 3 + proto/LOCAL_RECIPIENT_README.html | 3 +- proto/MAILLOG_README.html | 10 + proto/MILTER_README.html | 2 +- proto/MONGODB_README.html | 263 ++++++++ proto/Makefile.in | 16 + proto/POSTSCREEN_README.html | 4 +- proto/TLS_README.html | 164 +++-- proto/access | 4 +- proto/aliases | 14 +- proto/canonical | 22 +- proto/generic | 6 +- proto/header_checks | 46 +- proto/master | 12 +- proto/mongodb_table | 240 +++++++ proto/mysql_table | 18 + proto/pcre_table | 11 +- proto/pgsql_table | 11 + proto/postconf.proto | 738 +++++++++++++++----- proto/regexp_table | 11 +- proto/relocated | 6 +- proto/socketmap_table | 2 +- proto/stop | 35 +- proto/stop.double-cc | 2 + proto/stop.double-history | 87 ++- proto/stop.double-install-proto-text | 4 + proto/stop.double-proto-html | 118 +++- proto/stop.spell-cc | 42 +- proto/stop.spell-history | 20 + proto/stop.spell-proto-html | 17 + proto/virtual | 22 +- src/bounce/bounce_notify_util.c | 13 +- src/bounce/with-msgid-with-filter-no-thread.ref | 2 +- src/bounce/with-msgid-with-filter-with-thread.ref | 2 +- src/cleanup/Makefile.in | 44 +- src/cleanup/cleanup.c | 24 +- src/cleanup/cleanup_addr.c | 6 +- src/cleanup/cleanup_init.c | 2 + src/cleanup/cleanup_message.c | 5 + src/cleanup/cleanup_milter.c | 9 + src/cleanup/cleanup_milter.in18a | 8 + src/cleanup/cleanup_milter.in18b | 8 + src/cleanup/cleanup_milter.in18c | 9 + src/cleanup/cleanup_milter.in18d | 8 + src/cleanup/cleanup_milter.ref18a1 | 1 + src/cleanup/cleanup_milter.ref18a2 | 29 + src/cleanup/cleanup_milter.ref18b1 | 1 + src/cleanup/cleanup_milter.ref18b2 | 27 + src/cleanup/cleanup_milter.ref18c1 | 1 + src/cleanup/cleanup_milter.ref18c2 | 29 + src/cleanup/cleanup_milter.ref18d1 | 1 + src/cleanup/cleanup_milter.ref18d2 | 27 + src/cleanup/test-queue-file18 | Bin 0 -> 653 bytes src/dns/Makefile.in | 26 +- src/dns/dns_lookup.c | 8 +- src/dns/dns_rr_test.c | 433 ++++++++++++ src/dns/mxonly_test.ref | 2 +- src/dns/no-mx.ref | 6 +- src/dns/test_dns_lookup.c | 5 +- src/dnsblog/dnsblog.c | 3 +- src/global/Makefile.in | 31 +- src/global/dict_ldap.c | 4 +- src/global/dict_mongodb.c | 570 ++++++++++++++++ src/global/dict_mongodb.h | 43 ++ src/global/dict_mysql.c | 87 ++- src/global/dict_pgsql.c | 73 +- src/global/dict_sqlite.c | 2 +- src/global/mail_addr_find.c | 4 +- src/global/mail_date.c | 9 +- src/global/mail_dict.c | 4 + src/global/mail_params.c | 19 +- src/global/mail_params.h | 32 +- src/global/mail_proto.h | 7 + src/global/mail_version.h | 4 +- src/global/maillog_client.c | 2 +- src/global/maps.c | 12 +- src/global/wildcard_inet_addr.c | 2 +- src/local/command.c | 5 +- src/local/local.c | 31 +- src/master/master.c | 12 +- src/master/master_ent.c | 8 +- src/oqmgr/qmgr_deliver.c | 4 +- src/pipe/pipe.c | 9 + src/postalias/postalias.c | 2 +- src/postcat/postcat.c | 6 +- src/postconf/Makefile.in | 85 ++- src/postconf/postconf.c | 40 +- src/postconf/postconf.h | 7 +- src/postconf/postconf_dbms.c | 49 +- src/postconf/postconf_unused.c | 112 +++- src/postconf/postconf_user.c | 16 +- src/postconf/test29.ref | 3 + src/postconf/test72.ref | 3 + src/postconf/test73.ref | 3 + src/postconf/test74.ref | 3 + src/postconf/test75.ref | 3 + src/postconf/test76.ref | 9 + src/postdrop/postdrop.c | 2 +- src/postfix/postfix.c | 3 +- src/postkick/postkick.c | 2 +- src/postlock/postlock.c | 2 +- src/postlog/postlog.c | 6 + src/postlogd/postlogd.c | 14 +- src/postmap/postmap.c | 2 +- src/postqueue/showq_json.c | 79 +-- src/postscreen/postscreen.c | 32 +- src/postscreen/postscreen_smtpd.c | 16 +- src/postsuper/postsuper.c | 2 +- src/posttls-finger/posttls-finger.c | 64 +- src/proxymap/proxymap.c | 38 +- src/qmgr/qmgr.c | 2 +- src/qmgr/qmgr_deliver.c | 4 +- src/qmqpd/qmqpd.c | 2 +- src/sendmail/sendmail.c | 7 +- src/smtp/lmtp_params.c | 2 + src/smtp/smtp.c | 136 ++-- src/smtp/smtp.h | 2 + src/smtp/smtp_addr.c | 2 +- src/smtp/smtp_params.c | 2 + src/smtp/smtp_proto.c | 2 + src/smtp/smtp_sasl_glue.c | 4 +- src/smtp/smtp_tls_policy.c | 56 +- src/smtpd/Makefile.in | 11 +- src/smtpd/smtpd.c | 117 +++- src/smtpd/smtpd.h | 4 + src/smtpd/smtpd_check.c | 177 ++--- src/smtpd/smtpd_check_backup.ref | 1 + src/smtpd/smtpd_deprecated.in | 20 + src/smtpd/smtpd_deprecated.ref | 35 + src/smtpd/smtpd_exp.ref | 10 +- src/smtpd/smtpd_sasl_glue.c | 4 + src/smtpd/smtpd_state.c | 1 + src/smtpstone/smtp-source.c | 94 ++- src/tls/tls.h | 31 +- src/tls/tls_client.c | 157 ++++- src/tls/tls_dane.c | 77 ++- src/tls/tls_fprint.c | 53 +- src/tls/tls_misc.c | 129 +++- src/tls/tls_proxy.h | 13 +- src/tls/tls_proxy_client_print.c | 1 + src/tls/tls_proxy_client_scan.c | 3 +- src/tls/tls_proxy_context_print.c | 4 + src/tls/tls_proxy_context_scan.c | 4 +- src/tls/tls_server.c | 73 +- src/tls/tls_verify.c | 18 +- src/tlsproxy/tlsproxy.c | 11 + src/trivial-rewrite/resolve.c | 2 +- src/trivial-rewrite/trivial-rewrite.c | 17 +- src/util/Makefile.in | 47 +- src/util/argv.c | 57 +- src/util/argv.h | 2 + src/util/casefold.c | 2 +- src/util/dict_inline.c | 2 +- src/util/dict_thash.c | 6 +- src/util/dict_utf8.c | 4 +- src/util/inet_prefix_top.c | 1 + src/util/logwriter.c | 34 +- src/util/logwriter.h | 1 + src/util/midna_domain.c | 4 +- src/util/parse_utf8_char.h | 122 ++++ src/util/printable.c | 162 ++++- src/util/quote_for_json.c | 218 ++++++ src/util/readlline.c | 231 ++++++- src/util/stringops.h | 3 + src/util/sys_defs.h | 7 + src/util/valid_hostname.c | 13 +- src/util/valid_hostname.in | 6 + src/util/valid_hostname.ref | 10 + src/util/valid_utf8_string.c | 247 +++++-- src/util/vstream.c | 34 +- src/xsasl/xsasl_cyrus_server.c | 4 + src/xsasl/xsasl_server.c | 9 +- 316 files changed, 12719 insertions(+), 3748 deletions(-) create mode 100644 README_FILES/DEPRECATION_README create mode 100644 README_FILES/MONGODB_README create mode 100644 RELEASE_NOTES-3.8 create mode 100644 html/DEPRECATION_README.html create mode 100644 html/MONGODB_README.html create mode 100644 html/mongodb_table.5.html create mode 100644 man/man5/mongodb_table.5 create mode 100755 mantools/check-see-postconf-d-output create mode 100755 mantools/check-snapshot-nonprod create mode 100644 proto/DEPRECATION_README.html create mode 100644 proto/MONGODB_README.html create mode 100644 proto/mongodb_table create mode 100644 src/cleanup/cleanup_milter.in18a create mode 100644 src/cleanup/cleanup_milter.in18b create mode 100644 src/cleanup/cleanup_milter.in18c create mode 100644 src/cleanup/cleanup_milter.in18d create mode 100644 src/cleanup/cleanup_milter.ref18a1 create mode 100644 src/cleanup/cleanup_milter.ref18a2 create mode 100644 src/cleanup/cleanup_milter.ref18b1 create mode 100644 src/cleanup/cleanup_milter.ref18b2 create mode 100644 src/cleanup/cleanup_milter.ref18c1 create mode 100644 src/cleanup/cleanup_milter.ref18c2 create mode 100644 src/cleanup/cleanup_milter.ref18d1 create mode 100644 src/cleanup/cleanup_milter.ref18d2 create mode 100644 src/cleanup/test-queue-file18 create mode 100644 src/dns/dns_rr_test.c create mode 100644 src/global/dict_mongodb.c create mode 100755 src/global/dict_mongodb.h create mode 100644 src/postconf/test72.ref create mode 100644 src/postconf/test73.ref create mode 100644 src/postconf/test74.ref create mode 100644 src/postconf/test75.ref create mode 100644 src/postconf/test76.ref create mode 100644 src/smtpd/smtpd_deprecated.in create mode 100644 src/smtpd/smtpd_deprecated.ref create mode 100644 src/util/parse_utf8_char.h create mode 100644 src/util/quote_for_json.c diff --git a/.indent.pro b/.indent.pro index 4ba45d0..8ee03db 100644 --- a/.indent.pro +++ b/.indent.pro @@ -88,6 +88,7 @@ -TDICT_LDAP -TDICT_LMDB -TDICT_MC +-TDICT_MONGODB -TDICT_MYSQL -TDICT_NI -TDICT_NIS @@ -248,6 +249,7 @@ -TNVTABLE_INFO -TOPTIONS -TPCF_DBMS_INFO +-TPCF_DEPR_PARAM_INFO -TPCF_EVAL_CTX -TPCF_MASTER_EDIT_REQ -TPCF_MASTER_ENT @@ -411,6 +413,7 @@ -TXSASL_SERVER_IMPL -TXSASL_SERVER_IMPL_INFO -Tbind_props +-Tbson_iter_t -Tcipher_probe_t -Td2i_X509_t -Tdane_digest diff --git a/HISTORY b/HISTORY index 3892273..959e0fa 100644 --- a/HISTORY +++ b/HISTORY @@ -27056,14 +27056,28 @@ Apologies for any names omitted. sometimes incomplete) lookup table configuration info with a reference to the corresponding *_table(5) manpage. +20230417 + + Cleanup: in the MySQL client configuration file, the default + characterset is now configurable with the "charset" attribute. + Previously, the default was determined by the MySQL + implementation (utf8mb4 as of MySQL 8.0, latin1 with older + versions). This setting implicitly controls the collation + order. Files: proto/mysql_table, global/dict_mysql.c. + 20230418 - Bugfix defect (introduced: Postfix 3.2): the MySQL client - could return "not found" instead of "error" (for example, - resulting in a 5XX SMTP status instead of 4XX) during the - time that all MySQL server connections were turned down - after error. Found during code maintenance. File: - global/dict_mysql.c. + Bugfix (introduced: Postfix 3.2): the MySQL client could + return "not found" instead of "error" (for example, resulting + in a 5XX SMTP status instead of 4XX) during the time that + all MySQL server connections were turned down after error. + Found during code maintenance. File: global/dict_mysql.c. + +20230419 + + Cleanup: in the PostgreSQL client, cosmetic changes to make + the code easier to maintain (in preparation for adding new + functionality). File: global/dict_pgsql.c. 20230428 @@ -27091,6 +27105,74 @@ Apologies for any names omitted. ...' with a single service definition 'name2 type2 ...'. Problem reported by SATOH Fumiyasu. File: postconf/postconf_edit.c. +20230503 + + Documentation: clarified the relationship between + smtp_bind*address, inet_interfaces, and system-chosen source + IP addresses for outbound SMTP/LMTP connections. File: + proto/postconf.proto. + +20230504 + + Documentation: clarified the relationships between + local_transport, virtual_mailbox_transport, relay_transport, + default_transport, relay_host, sender_dependent_relayhost_maps, + sender_dependent_default_transport_maps, and their precedences + when determining a delivery transport or next-hop destination, + in ADDRESS_REWRITING_README and in the text that defines + individual configuration features. Files: proto/postconf.proto, + proto/ADDRESS_REWRITING_README.html. + +20230505 + + Documentation: clarified the differences between virtual + and local aliasing, in four places. Files: mantools/postlink, + proto/postconf.proto, proto/ADDRESS_REWRITING_README.html. + cleanup/cleanup.c, local/local.c, smtpd/smtpd.c. + + Usability: improved error message when master.cf specifies + a wild-card network listener (like "smtp inet ... smtpd") + while inet_interfaces is empty. File: master/master_ent.c. + + More documentation updates for local aliasing versus virtual + aliasing. Files: proto/aliases, proto/virtual, postfix/postfix.c. + +20230506 + + Cleanup: simplified the master code to handle an empty + inet_interfaces setting. it is now closer to the original + code. Also documented that wildcard_inet_addr_list() will + not return an empty list. Files: master/master_ent.c, + global/own_inet_addr_list.c. + +20230507 + + Documentation: fine tuning of text about local aliasing + versus virtual aliasing. Files: proto/postconf.proto, + proto/aliases, proto/virtual, proto/ADDRESS_REWRITING_README.html. + +20230508 + + Documentation: more fine tuning of text about local aliasing + versus virtual aliasing, and inet_interfaces. Files: + proto/postconf.proto, proto/aliases, proto/virtual, + proto/ADDRESS_REWRITING_README.html. + +20230516 + + Bugfix (defect introduced: Postfix 3.4): the postlog(1) + command created a logfile with permissions 0644, but the + postlogd(8) daemon created it with permissions 0600, for + example after "postfix logrotate". The discrepancy is now + eliminated, and the permissions when creating a file are + now configurable with the "maillog_file_permissions" + parameter, default 0600 for backwards compatibility. Files: + mantools/postlink, proto/MAILLOG_README.html, proto/postconf.proto, + global/mail_params.c, global/mail_params.h, global/Makefile.in, + master/master.c, postlog/postlog.c, postlogd/postlogd.c, + util/logwriter.c, util/logwriter.h, util/Makefile.in, + util/vstream.c. + 20230517 Bugfix (defect introduced: Postfix 3.8) the posttls-finger @@ -27101,6 +27183,17 @@ Apologies for any names omitted. 20230519 + Cleanup: fixed postconf tests for dynamically-linked builds. + File: postconf/Makefile.in. + +20230521 + + Bitrot: library error messages in SMTP server tests. File: + smtpd/Makefile.in. + + Cleanup: removed some "the the" instances. Files: + proto/MILTER_README.html proto/stop.double-proto-html. + Bitrot: preliminary support for OpenSSL configuration files, primarily OpenSSL 1.1.1b and later. This introduces new parameters "tls_config_file" and "tls_config_name", which @@ -27117,13 +27210,13 @@ Apologies for any names omitted. 20230523 - Cleanup: use TLS_CLIENT_PARAMS to pass the OpensSSL 'init' - configurations. This information is independent from the - client or server TLS context, and therefore does not belong - in tls_*_init() or tls_*_start() calls. The tlsproxy(8) - server uses TLS_CLIENT_PARAMS to report differences between - its own global TLS settings, and those from its clients. - Files: posttls-finger/posttls-finger.c, smtp/smtp.c, + Cleanup: use TLS_CLIENT_PARAMS to pass the OpenSSL 'init' + configuration settings. These are global, i.e. apply to all + client TLS contexts, and they do not belong in tls_client_init() + or tls_client_start() calls. The tlsproxy(8) server uses + TLS_CLIENT_PARAMS information to warn about differences + between its own global TLS settings, and those from its + clients. Files: posttls-finger/posttls-finger.c, smtp/smtp.c, smtp/smtp_proto.c, tls/tls.h, tls/tls_proxy_client_misc.c, tls/tls_proxy_client_print.c, tls/tls_proxy_client_scan.c, tls/tls_proxy.h, tlsproxy/tlsproxy.c. @@ -27131,15 +27224,27 @@ Apologies for any names omitted. 20230524 Cleanup: reverted cosmetic-only changes to minimize the - patch footprint for OpenSSL INI file support; updated daemon - manpages with the new tls_config_file and tls_config_name - configuration parameters. Files: smtp/smtp.c, smtpd/smtpd.c, - tls/tls_client.c, tls/tls.h, tls/tls_server.c, tlsproxy/tlsproxy.c, + patch footprint for OpenSSL INI file support for stable + releases; updated daemon manpages with the new tls_config_file + and tls_config_name configuration parameters. Files: + smtp/smtp.c, smtpd/smtpd.c, tls/tls_client.c, tls/tls.h, + tls/tls_server.c, tlsproxy/tlsproxy.c, + +20230526 + + Documentation: clarified address class descriptions; added + the availability of back-ported OpenSSL INI file support + in stable releases. Files: proto/ADDRESS_CLASS_README.html, + proto/postconf.proto smtp/smtp.c, smtpd/smtpd.c, + tlsproxy/tlsproxy.c. + + Security: in the Postfix SMTP daemon, improved pipelining + detection and reporting; added code to detect illegal command + pipelining before the server greeting. File: smtpd/smtpd.c. 20230529 - Cleanup: made OpenSSL 'default' INI file support error - handling consistent with OpenSSL default behavior. Viktor + Cleanup: error handling for OpenSSL INI file support. Viktor Dukhovni. Files: proto/postconf.proto, tls/tls_misc.c. 20230602 @@ -27150,22 +27255,64 @@ Apologies for any names omitted. non-default tls_config_xxx settings. File: tls/tls_misc.c. Cleanup: added a multiple initialization guard in the - tls_library_init() function, and made an initialization - error sticky. File: tls/tls_misc.c. + tls_library_init() function, and made an initialization error + sticky. File: tls/tls_misc.c. -20230605 +20230603 Security: new parameter smtpd_forbid_unauth_pipelining - (default: no) to disconnect remote SMTP clients that violate + (default: yes) to disconnect remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. Files: global/mail_params.h, smtpd/smtpd.c, proto/postconf.proto. +20230610 + + Trouble shooting: when the postfix UID or postdrop GID is + also used by a non-Postfix account, log the UID or GID. + File: global/mail_params.c. + +20240703 + + Typo fix by Trent W. Buck. Files: proto/postconf.proto, proto/stop. + +20230807 + + Feature: optional support to request a raw public key instead + of a public-key certificate when a) the Postfix SMTP server + requests TLS authentication from a remote SMTP client, or + b) when the Postfix SMTP client initiates a TLS handshake + with a remote SMTP server. See RELEASE_NOTES for details. + Viktor Dukhovni. Files: mantools/postlink, proto/TLS_README.html, + proto/postconf.proto, RELEASE_NOTES, global/mail_params.h, + posttls-finger/posttls-finger.c, smtp/lmtp_params.c, + smtp/smtp.c, smtp/smtp.h, smtp/smtp_params.c, smtp/smtp_proto.c, + smtp/smtp_tls_policy.c, smtpd/smtpd.c, smtpd/smtpd_check.c, + tls/tls.h, tls/tls_client.c, tls/tls_dane.c, tls/tls_fprint.c, + tls/tls_misc.c, tls/tls_proxy.h, tls/tls_proxy_client_print.c, + tls/tls_proxy_client_scan.c, tls/tls_proxy_context_print.c, + tls/tls_proxy_context_scan.c, tls/tls_server.c, tls/tls_verify.c, + tlsproxy/tlsproxy.c. + +20230808 + + Documentation loose ends. Files: proto/postconf.proto, + RELEASE_NOTES. + 20230815 - Bugfix (bug introduced: 20140218): when opportunistic TLS fails - during or after the handshake, don't require that a probe - message spent a minimum time-in-queue before falling back to - plaintext. Problem reported by Serg. File: smtp/smtp.h. + Bugfix (defect introduced: 20140218): when an address + verification probe fails during or after an opportunistic + TLS handshake, immediately fall back to plaintext, without + enforcing a minimum time-in-queue. Problem reported by Serg. + File: smtp/smtp.h. + +20230820 + + Feature: smtp_sasl_password_result_delimiter, for the rare + case that the ":" character needs to be part of the username. + mantools/postlink, proto/postconf.proto, global/mail_params.h, + smtp/lmtp_params.c, smtp/smtp.c, smtp/smtp_params.c, + smtp/smtp_sasl_glue.c. 20230819 @@ -27179,12 +27326,81 @@ Apologies for any names omitted. *.other.example IN A 10.0.0.1 *.other.example IN TLSA ..certificate info... - Such syntax is blesed in RFC 1034 section 4.3.3. + Such syntax is blessed in RFC 1034 section 4.3.3. This problem was reported first in the context of TLSA record lookups. Files: util/valid_hostname.[hc], dns/dns_lookup.c. +20230831 + + Documentation: clarify the scope of local_recipient_maps. + Files: proto/LOCAL_RECIPIENT_README.html, proto/postconf.proto. + + Documentation loose ends. Files: HISTORY, dns/dns_lookup.c. + +20230901 + + Feature: force_mime_input_conversion (default: no) to + convert content that claims to be 8-bit into quoted-printable, + before header_checks, body_checks, Milters, and before + after-queue content filters. The typical use case is an MTA + that applies this conversion before signing outbound messages, + so that the signatures will remain valid when a message is + later delivered to an MTA that does not announce 8BITMIME + support, or when a message line exceeds the SMTP length + limit. Files: global/mail_params.c, cleanup/cleanup_message.c, + cleanup/cleanup.c, cleanup/cleanup_init.c, proto/postconf.proto, + mantools/postlink. + +20230902 + + Cleanup: renamed enforce_mime_input_conversion to + force_mime_input_conversion. + +20230903 + + Cleanup: removed support for MySQL < 4.0 (released 2003), + removed the deprecated mysql_escape_string() call, added + the preferred mysql_real_escape_string_quote() call, and + added error handling for the unlikely case that the legacy + mysql_real_escape_string() returns an error. File: + global/dict_mysql.c. + +20230906 + + Documentation: the postconf(5) manpage did not document + that the force_mime_input_conversion feature was introduced + in Postfix 3.9. Viktor Dukhovni. File: proto/postconf.proto. + +20230912 + + Cleanup: record the use of a raw public key in Received: + headers, when the Postfix SMTP server or the remote SMTP + client presents a raw public key. Viktor Dukhovni. File: + smtpd/smtpd.c. + +20230923 + + Documentation: updated descriptions of the postscreen_*_ttl + and postscreen_dnsbl_allowlist_threshold parameters. Files: + proto/postconf.proto, postscreen/postscreen.c. + +20230916 + + Documentation: fixed missing and misplaced quotes in "see + 'postconf -d' output". Reported by наб. Files: Makefile.in, + mantools/check-see-postconf-d-output, proto/postconf.proto, + global/maillog_client.c, master/master.c, smtp/smtp.c, + smtpd/smtpd.c. + +20230917 + + Documentation: added a note to smtp_tls_security_level and + smtp_tls_policy_maps, that the level "MAY" will fall back + to plaintext after TLS failure, when a message has spent + minimal_backoff_time in the mail queue. File: proto/postconf.proto. + 20230929 Bugfix (defect introduced Postfix 2.5, 20080104): the Postfix @@ -27193,6 +27409,35 @@ Apologies for any names omitted. error in TLS wrappermode. Reported by Andreas Kinzler. File: smtpd/smtpd.c. +20230923 + + This changes the smtp-source test program, to avoid the + need to configure a large number of "valid" recipient + addresses in Postfix, by using a recipient address extension + in the form of a sequence number. The change is to append + the optional recipient address sequence number to the + recipient address localpart, instead of prepending it. To + use that sequence number as a recipient address extension, + specify an explicit address delimiter in the address + localpart, as in "-t localpart+@domain" or "-t localpart+" + where "+" is the Postfix recipient address delimiter. File: + smtpstone/smtp-source.c. + +20230924 + + Cleanup: simplified the smtp-source numbered recipient + implementation and documentation. File: smtpstone/smtp-source.c. + + Documentation: added smtp_balance_inet_protocols to the + text with smtp_address_preference caveats. File: + proto/postconf.proto. + +20230926 + + Documentation: added a section to smtp_balance_inet_protocols + to address the problem that servers may flag mail received + over IPv6 as more spammy. File: proto/postconf.proto. + 20231006 Usability: the Postfix SMTP server now attempts to log the @@ -27204,6 +27449,62 @@ Apologies for any names omitted. on code by Jozsef Kadlecsik. Files: xsasl/xsasl_server.c, xsasl/xsasl_cyrus_server.c, smtpd/smtpd_sasl_glue.c. +20231008 + + Cleanup: enforce stricter UTF8 checks in printable(). Factor + out the UTF8 parser, so that it can be shared between + valid_utf8_string() and printable(). Wietse Venema, with + tests by Viktor Dukhovni. Files: util/valid_utf8_string.c, + util/printable.c, util/parse_utf8_char.h, util/printable.in, + util/printable.ref. + +20231010 + + Cleanup: printable() uses once again a single-pass algorithm. + Converted printable() test files to built-in test cases with + proper logging, and removed the printable() test files and + git metadata. Added similar tests for the valid_utf8_string() + function. Files: util/valid_utf8_string.c, util/printable.c, + util/parse_utf8_char.h, util/Makefile.in. + +20231011 + + Documentation: fixed some instances of "." instead of ",". + Files: proto/POSTSCREEN_README.html, proto/socketmap_table. + + Cleanup: finer-grained unit tests for valid_utf8_string(). + File: util/valid_utf8_string.c. + + Style: converted failed test reports to "got before want" + order, and converted tests to "fail before pass" order. + Files: util/valid_utf8_string.c, util/printable.c. + + Cleanup: added a valid_utf8_stringz() function to simplify + most calls to validate null-terminated strings, eliminating + the runtime cost and code maintenance cost of 17 strlen() + calls. Files: src/bounce/bounce_notify_util.c, + src/cleanup/cleanup_addr.c, src/global/dict_ldap.c, + src/global/dict_mysql.c, src/global/dict_pgsql.c, + src/global/dict_sqlite.c, src/oqmgr/qmgr_deliver.c, + src/postalias/postalias.c, src/postmap/postmap.c, + src/postscreen/postscreen_smtpd.c, src/qmgr/qmgr_deliver.c, + src/smtpd/smtpd.c, src/smtpd/smtpd_check.c, + src/trivial-rewrite/resolve.c, src/util/casefold.c, + src/util/dict_inline.c, src/util/dict_thash.c, + src/util/dict_utf8.c, src/util/midna_domain.c, + src/util/printable.c, src/util/stringops.h, + src/util/valid_utf8_string.c. + + Cleanup: added unit tests to the readlline module, with + multiline input that contains embedded comments, input that + contains a null byte, text not ending in newline. File: + readlline.c. + +20231024 + + Cleanup: emit place holder text when no SASL authentication + failure reason is available. File: smtpd/smtpd_sasl_glue.c. + 20231026 Bugfix (defect introduced: Postfix 2.11): in forward_path, @@ -27213,39 +27514,15 @@ Apologies for any names omitted. a configured recipient delimiter value. Reported by Tod A. Sandman. Files: proto/postconf.proto, local/local_expand.c. -20240109 - - Security (outbound SMTP smuggling): with the default setting - "cleanup_replace_stray_cr_lf = yes" Postfix will replace - stray or characters in message content with a - space character. This prevents Postfix from enabling - outbound (remote) SMTP smuggling, and it also makes evaluation - of Postfix-added DKIM etc. signatures independent from how - a remote mail server handles stray or characters. - Files: global/mail_params.h, cleanup/cleanup.c, - cleanup/cleanup_message.c, mantools/postlink, proto/postconf.proto. +20231027 -20240112 + Cleanup: missing 'smtpd_tls_enable_rpk' parameter definition + in test driver. File: smtpd/smtpd_check.c. - Security (inbound SMTP smuggling): with "smtpd_forbid_bare_newline - = normalize" (default "no" for Postfix < 3.9), the Postfix - SMTP server requires the standard End-of-DATA sequence - ., and otherwise allows command or message - content lines ending in the non-standard , processing - them as if the client sent the standard . +20231030 - The alternative setting, "smtpd_forbid_bare_newline = reject" - will reject any command or message that contains a bare - , and is more likely to cause problems with legitimate - clients. - - For backwards compatibility, local clients are excluded by - default with "smtpd_forbid_bare_newline_exclusions = - $mynetworks". - - Files: mantools/postlink, proto/postconf.proto, - global/mail_params.h, global/smtp_stream.c, global/smtp_stream.h, - smtpd/smtpd.c, smtpd/smtpd_check.[hc]. + Cleanup: explicit %.100s limits for client-controlled strings + in SASL error logging. File: smtpd/smtpd_sasl_glue.c. 20231102 @@ -27260,6 +27537,55 @@ Apologies for any names omitted. Cleanup: Postfix SMTP server response with an empty authentication failure reason. File: smtpd/smtpd_sasl_glue.c. + Cleanup: proxymap error message when the service name is + not "proxymap" or "proxywrite". File: proxymap/proxymap.c. + +20231109 + + Portability: MariaDB emulates MySQL >= 5.7.6, but does not + implement mysql_real_escape_string_quote(). Fix by Levente + Birta. File: global/dict_mysql.c. + + Portability: more precise MYSQL_VERSION_ID check. File: + global/dict_mysql.c. + +20231112 + + Robustness: don't loop on an 'unfinished' queue file that + still has its all-zero SIZE record. File: postcat/postcat.c. + +20231126 + + Cleanup: implementation and documentation for the selection + of SMTP versus LMTP client protocol and parameters, based + on process name. Files: smtp/smtp.c, global/mail_proto.h, + proto/postconf.proto. + + Cleanup: documented (in proxymap source code) the complexities + of determining the optimal proxywrite service process limit, + and make the 'invalid' proxymap service name error message + more similar to the error message for an invalid SMTP/LMTP + client process name. File: proxymap/proxymap.c. + +20231127 + + Documentation: in the stock main.cf file, mailbox_command + uses $default_privs, not $default_user. Vijay Sarvepalli, + Cert/CC. File: conf/main.cf. + +20231202 + + Bugfix: posttls-finger certificate match expectations for + opportunistic DANE incorrectly defaulted to ("nexthop", + "hostname") instead of ("nexthop", "dot-nexthop"), when no + TLSA records were found. Viktor Dukhovni. File: posttls-finger.c. + +20231204 + + Documentation: updated comments on address validation in + smtpd_check.c, making them consistent with the implementation. + File: smtpd/smtpd_check.c. + 20231208 Bugfix (defect introduced: Postfix 3.1, date: 20151128): @@ -27267,6 +27593,17 @@ Apologies for any names omitted. character as \uXXXX. Found during code maintenance. File: postqueue/showq_json.c. +20231209 + + Feature: the local(8) delivery agent exports an ENVID + environment variable with the RFC 3461 envelope ID if + available. Files: local/command.c, local/local.c, + proto/postconf.proto. + + Feature: the pipe(8) delivery agent supports an ${envid} + command-line attribute that expands to the RFC 3461 envelope + ID if available. File: pipe/pipe.c. + 20231211 Cleanup: posttls-finger certificate match expectations for @@ -27289,31 +27626,296 @@ Apologies for any names omitted. Received: header) when handling requests from a Milter to delete or update an existing header. Problem report by Carlos Velasco. This change was verified to have no effect - on requests from a Milter to add or insert a header. File: - cleanup/cleanup_milter.c. + on requests from a Milter to add or insert a header. Files: + cleanup/cleanup_milter.c, cleanup/Makefile.in, + cleanup/test-queue-file18, cleanup/cleanup_milter.in18[a-d], + cleanup/cleanup_milter.ref18[a-d][12]. + +20231221 + + Security: with "smtpd_forbid_bare_newline = yes" (the default + for Postfix 3.9), reply with "Error: bare received" + and disconnect when an SMTP client sends a line ending in + , violating the RFC 5321 requirement that lines must + end in . This prevents SMTP smuggling attacks that + target a recipient at a Postfix server. For backwards + compatibility, local clients are excluded by default with + "smtpd_forbid_bare_newline_exclusions = $mynetworks". Files: + mantools/postlink, proto/postconf.proto, global/mail_params.h, + global/smtp_stream.c, global/smtp_stream.h, smtpd/smtpd.c. + +20240104 + + Cleanup: when the Postfix SMTP server rejects bare , + log the helo, mail and rcpt information if available. Files: + smtpd/smtpd.c, smtpd/smtpd_check.c. + + Cleanup: when the Postfix SMTP server rejects bare , + keep reading message content after an unexpected . + or ., before responding. This increases the + likelihood that the client will actually see the Postfix + response and remove the attack from their mail queue. Files: + smtpd/smtpd.c, global/smtp_stream.[hc], global/cleanup_user.h. + + Cleanup: added smtpd_forbid_bare_newline settings "reject" + and "normalize". The default setting "normalize" (and "yes") + will accept bare newlines from local or remote SMTP clients, + but if any DATA content line ends in , require the + standard End-of-DATA form . and skip + non-standard End-of-DATA forms. This may fail to receive + email from legitimate clients that send a mix of lines + ending in and . If such clients exist, they + need to be excluded with smtpd_forbid_bare_newline_exclusions. + Files: proto/postconf.proto, global/mail_params.h, + smtpd/smtpd.c. + + Tooling: mantools/dehtml was breaking words in code examples, + causing false spellchecker errors. File: mantools/dehtml, + proto/stop.double-proto-html. + +20240105 + + Cleanup: don't spam the log with unexpected End-of-DATA + forms. Files: proto/postconf.proto, smtpd/smtpd.c, + RELEASE_NOTES. + +20240106 + + Inbound smuggling: with smtpd_forbid_bare_newline enabled, + do not "strip" extra characters before . This avoids + ambiguity when a client sends extra characters as in + .. There is no smuggling vulnerability + because there is no mail system will send the above + sequence (mail systems send .. instead). + But this change will silence some testing tools. More at + https://www.postfix.org/false-smuggling-claims.html. File: + global/smtp_stream.c. + +20240109 + + Outbound smuggling: with "cleanup_replace_stray_cr_lf = + yes" (the default) Postfix will replace stray or + characters in message content with a space character. This + prevents Postfix from enabling outbound (remote) SMTP + smuggling, and it also makes evaluation of Postfix-added + DKIM etc. signatures independent from how a remote mail + server handles stray or characters. Files: + global/mail_params.h, cleanup/cleanup.c, cleanup/cleanup_message.c, + mantools/postlink, proto/postconf.proto. + +20240110 + + Cleanup: the smtpd_forbid_bare_newline settings "normalize" + and "reject" are now more similar. Both now unconditionally + require the standard End-of-DATA sequence .. + Files: smtpd/smtpd.c, proto/postconf.proto, RELEASE_NOTES. + +20240112 + + Cleanup: updated comments and identifiers because the bare + newline handling has evolved. Files: global/smtp_stream.[hc], + Files: global/smtp_stream.[hc], smtpd/smtpd.c. + +20240116 + + Reverted some changes after postfix-3.9-20240112, and updated + documentation. + +20240121 + + Documentation: "smtpd_forbid_bare_newline = reject" will + reject email from services that use BDAT to send MIME text + containing a bare newline (RFC 3030 Section 3 requires + canonical MIME format for text message types, defined in + RFC 2045 Sections 2.7 and 2.8) Files: proto/postconf.proto, + RELEASE_NOTES. + + Baseline for back porting the SMTP smuggling fixes to Postfix + 3.8.5, 3.7.10, 3.6.14, and 3.5.24. 20240124 + Feature: with "smtpd_forbid_bare_newline = note", the Postfix + SMTP server notes in the log if it received any lines with + bare LF. Otherwise, "note" is like "normalize". The + information is formatted as "disconnect from name[address] + ... notes=bare_lf". The new value is expected to become + a list of comma-separated names. Files: smtpd/smtpd.[hc]. + + Cleanup: require that a stable release disables SNAPSHOT + and NONPROD features. File: mantools/check-snapshot-nonprod. + + Bugfix (defect introduced: Postfix 3.4): the SMTP server's + BDAT command handler could be tricked to read $message_size_limit + bytes into memory. Found during code maintenance. File: + smtpd/smtpd.c. + + Feature: never too late, an SMTP server HELP command that + lists the implemented commands. Some commands may be + implemented but not available due to smtpd_discard_ehlo_keywords + or access control limitations. Files: smtpd/smtpd.[hc], + util/argv.[hc]. + Workaround: tlsmgr logfile spam. Some OS lies under load: it says that a socket is readable, then it says that the socket has unread data, and then it says that read returns EOF, causing Postfix to spam the log with a warning message. File: tlsmgr/tlsmgr.c. - Bugfix (defect introduced: Postfix 3.4): the SMTP server's - BDAT command handler could be tricked to read $message_size_limit - bytes into memory. Found during code maintenance. File: - smtpd/smtpd.c. +20240125 + + Cleanup: tlsmgr.c fix 20240124. File: tlsmgr/tlsmgr.c. + + Documentation: updated obsolete "CONFIGURATION PARAMETERS" + summaries in Postfix manpages, with current text from the + postconf(5) manpage. Files: proto/generic, proto/header_checks, + proto/aliases, proto/canonical, proto/relocated, + postdrop/postdrop.c, postsuper/postsuper.c, sendmail/sendmail.c, + dnsblog/dnsblog.c, postkick/postkick.c, postlock/postlock.c, + qmgr/qmgr.c, qmqpd/qmqpd.c, trivial-rewrite/trivial-rewrite.c. + +20240129 + + Documentation: be more precise about server lookups with + MX or SRV records. File: smtp/smtp.c. + + Documentation: postlogd is not a short-running process. It + wil keep running until it reaches the max_idle limit. File: + postlogd/postlogd.c. + + Cleanup (no semantic change): in the mysql: and pgsql: + clients, made the hard-coded idle and retry timer settings + configurable, and updated the mysql_table(5) and pgsql_table(5) + manpages. Files: global/dict_mysql.c, global/dict_pgsql.c, + proto/mysql_table, proto/pgsql_table. + +20230130 + + Reproducible build: added LC_ALL=C to the top of the makedefs + script. + +20240206 + + Documentation: in COMPATIBILITY_README, the descriptions + of smtpd_relay_restrictions and smtputf8_enable were grouped + under the wrong compatibility level value. Reported by Rune + Philosof. File: proto/COMPATIBILITY_README.html. + + Compatibility: the RFC 5322 date and time specification + recommends (i.e. should) that a single space be used in + each place that FWS appears. To avoid a breaking change, + Postfix now formats numerical days as two-digit days, i.e. + days 1-9 have a leading zero instead of a leading space. + Files: util/sys_defs.h global/mail_date.c. + + Documentation: the post-install(1) manpage now lists + $config_directory/makedefs.out as one of the installed + files. File: postfix-install. + +20240208 + + Refactored the JSON string quoting function, so that it can + be shared between the postqueue command and the MongoDB + client implementation. Files: util.quote_for_json.c, + util/stringops.h, postqueue/showq_json.c. + + MongoDB client support, contributed by Hamid Maadani, based + on earlier code by Stephan Ferraro. Files: conf/dynamicmaps.cf, + conf/postfix-files, makedefs, mantools/postlink, + proto/DATABASE_README.html, proto/Makefile.in, + proto/MONGODB_README.html, proto/mongodb_table, + global/dict_mongodb.c, global/dict_mongodb.h, global/mail_dict.c, + global/Makefile.in, postconf/Makefile.in, proto/INSTALL.html, + postfix/postfix.c. 20240209 Performance: eliminate worst-case behavior where the queue - manager defers delivery to all destinations over a specific + manager deferred delivery to all destinations over a specific delivery transport, after only a single delivery agent failure. The scheduler now throttles one destination, and allows deliveries to other destinations to keep making progress. Files: *qmgr/qmgr_deliver.c. +20240210 + + Documentation: introductory text for SMTP and LMTP lookup + strategies. File: smtp/smtp.c. + +20240211 + + Documentation: updated the text for the new "notes=" attribute + in SMTP server "disconnect" logging. File: proto/postconf.proto. + +20240212 + + Documentation: emphasize that email address patterns and + host name/address patterns for indexed etc. files are really + for indexed etc. files. File: proto/access. + + Documentation: mail_date(3) manpage. File: global/mail_date.c. + +20240213 + + Tests: updated tests that had suffered from bit rot. Files: + bounce/with-msgid-with-filter-no-thread.ref, + bounce/with-msgid-with-filter-with-thread.ref, + src/dns/mxonly_test.ref, dns/no-mx.ref. + + Logging: indicate which (usually, substring) lookups are + skipped. File: global/maps.c. + +20240215 + + Portability: Clang versions that predate support for the + C23 standard do not allow a declaration immediately after + a (switch) label. The workaround is to add a null statement + between label and declaration. File: global/dict_mongodb.c. + + Documentation: minor edits. Files: proto/mongodb_README.html, + proto/mongodb_table.html. + +20240216 + + Documentation: dropped text about partial matches from the + check_{client,helo,sender,recipient,etrn}_access summaries, + deferring to the access(5) manpage for details, for consistency + with the check_xx_yy_access features. File: proto/postconf.proto. + + Cleanup: missing mongodb checks in the postconf command, + missing mongodb under "postconf -m" manpage entry. Files: + postconf/postconf.c, postconf/postconf_dbms.c. + +20240218 + + Deprecation: the Postfix SMTP server logs a warning when + "permit_mx_backup" is used (support for restriction + "permit_mx_backup" will be removed from Postfix; instead, + use "relay_domains"). File: smtpd/smtpd_check.c. + + Deprecation: the postconf command logs a warning when the + following parameters are specified in main.cf or master.cf: + xxx_use_tls, xxx_enforce_tls (use the corresponding + xxx_security_level setting instead); xxx_per_site (use the + corresponding xxx_policy_maps setting instead); disable_dns_lookups + (use smtp_dns_support_level instead); smtpd_tls_dh1024_param_file, + smtpd_tls_eecdh_grade (do not specify, leave at default). + Files: postconf/postconf.c, postconf/postconf_unused.c. + proto/postconf.proto. + + Cleanup: add "postconf -q" option to avoid redundant warnings + about unused or deprecated parameter settings when upgrading + or installing Postfix. Such warnings are still logged with + the commands postfix start, start-fg, check, reload, or + status. Files: postconf/postconf.c, postconf/postconf_dbms.c, + postconf/postconf.h, conf/postfix-script, conf/post-install, + postfix-install. + +20240221 + + Documentation: the text for TLS loglevel 2 was incomplete. + File: proto/postconf.proto. + 20240226 Safety: drop and log over-size DNS responses resulting in @@ -27326,3 +27928,48 @@ Apologies for any names omitted. restrictions. Files: dns/dns.h, dns/dns_lookup.c, dns/dns_rr.c, dns/test_dns_lookup.c, posttls-finger/posttls-finger.c, smtp/smtp_addr.c, smtpd/smtpd_check.c. + +20240227 + + Documentation: document the need to disable regular expression + special characters when using $name inside an inlined + pattern. Files: proto/pcre_table, proto/regexp_table. + +20240228 + + Cleanups. Fixed some dns_rr_create() calls in test code, + and reverted a workaround in the DNS record formatter; + files: dns/dns_rr_test.c, dns/dns_strrecord.c. Code formatting; + file: global/mail_addr_find.c. Added missing test reference; + file: postconf/test76.ref. + +20240229 + + Compatibility: moved the new DNS_RR.flags structure member + to the location of a "padding" hole (two bytes for ILP32 + systems, 6 bytes for LP64). File: dns/dns.h. + + Deprecation: removed permit_naked_ip_address, reject_maps_rbl, + and check_relay_domains. These have been logging deprecation + warnings since 2005 or earlier, and were removed from Postfix + documentation in 2004 (but who reads logs and documentation?). + Files: smtpd/smtpd_check.c, smtpd/smtpd_check_backup.ref, + smtpd/smtpd_exp.ref, smtpd/smtpd_deprecated.in, + smtpd/smtpd_deprecated.ref. + +20240302 + + Cleanup: fixed inconsistent formatting of deprecation warning + messages. Files: postconf/postconf_unused.c, postconf/test76.ref, + smtpd/smtpd_check. + + Documentation: DEPRECATION_README suggests replacements for + features that will be removed or than have been removed. + Files: proto/DEPRECATION_README.html, conf/postfix-files, + html/index.html, proto/Makefile.in. + +20240305 + + Documentation: in the master.cf documentation, added text + for "quoting" a command-line argument that starts with "{". + File: proto/master. diff --git a/INSTALL b/INSTALL index 5939a99..90b1b2d 100644 --- a/INSTALL +++ b/INSTALL @@ -376,27 +376,29 @@ whistles. Support for third-party databases etc. must be configured when Postfix is compiled. The following documents describe how to build Postfix with support for optional features: - _____________________________________________________________ - |Optional feature |Document |Availability| - |__________________________________|_____________|____________| - |Berkeley DB database |DB_README |Postfix 1.0 | - |__________________________________|_____________|____________| - |LMDB database |LMDB_README |Postfix 2.11| - |__________________________________|_____________|____________| - |LDAP database |LDAP_README |Postfix 1.0 | - |__________________________________|_____________|____________| - |MySQL database |MYSQL_README |Postfix 1.0 | - |__________________________________|_____________|____________| - |Perl compatible regular expression|PCRE_README |Postfix 1.0 | - |__________________________________|_____________|____________| - |PostgreSQL database |PGSQL_README |Postfix 2.0 | - |__________________________________|_____________|____________| - |SASL authentication |SASL_README |Postfix 1.0 | - |__________________________________|_____________|____________| - |SQLite database |SQLITE_README|Postfix 2.8 | - |__________________________________|_____________|____________| - |STARTTLS session encryption |TLS_README |Postfix 2.2 | - |__________________________________|_____________|____________| + ______________________________________________________________ + |Optional feature |Document |Availability| + |__________________________________|______________|____________| + |Berkeley DB database |DB_README |Postfix 1.0 | + |__________________________________|______________|____________| + |LMDB database |LMDB_README |Postfix 2.11| + |__________________________________|______________|____________| + |LDAP database |LDAP_README |Postfix 1.0 | + |__________________________________|______________|____________| + |MongoDB database |MONGODB_README|Postfix 3.9 | + |__________________________________|______________|____________| + |MySQL database |MYSQL_README |Postfix 1.0 | + |__________________________________|______________|____________| + |Perl compatible regular expression|PCRE_README |Postfix 1.0 | + |__________________________________|______________|____________| + |PostgreSQL database |PGSQL_README |Postfix 2.0 | + |__________________________________|______________|____________| + |SASL authentication |SASL_README |Postfix 1.0 | + |__________________________________|______________|____________| + |SQLite database |SQLITE_README |Postfix 2.8 | + |__________________________________|______________|____________| + |STARTTLS session encryption |TLS_README |Postfix 2.2 | + |__________________________________|______________|____________| Note: IP version 6 support is compiled into Postfix on operating systems that have IPv6 support. See the IPV6_README file for details. diff --git a/Makefile.in b/Makefile.in index 474e9b5..4b1fb33 100644 --- a/Makefile.in +++ b/Makefile.in @@ -117,7 +117,8 @@ manpages: # Some checks require a bin/postconf executable. pre-release-checks: typo-check missing-proxy-read-maps-check \ postlink-check postfix-files-check check-spell-history \ - check-double-history check-table-proto + check-double-history check-table-proto check-see-postconf-d-output \ + check-snapshot-nonprod postfix-files-check: mantools/check-postfix-files | diff /dev/null - @@ -158,6 +159,12 @@ check-double-history: check-table-proto: mantools/check-table-proto | diff /dev/null - +check-see-postconf-d-output: + mantools/check-see-postconf-d-output | diff /dev/null - + +check-snapshot-nonprod: + mantools/check-snapshot-nonprod + # The build-time shlib_directory setting must take precedence over # the installed main.cf settings, otherwise we can't update an # installed system from dynamicmaps=yes<->dynamicmaps=no or from diff --git a/README_FILES/AAAREADME b/README_FILES/AAAREADME index 9afa3b7..94d552e 100644 --- a/README_FILES/AAAREADME +++ b/README_FILES/AAAREADME @@ -15,6 +15,7 @@ GGeenneerraall ccoonnffiigguurraattiioonn * SMTPUTF8_README: SMTPUTF8 Support * MAILLOG_README: Postfix logging to file or stdout * COMPATIBILITY_README: Backwards-Compatibility Safety Net + * DEPRECATION_README: Deprecated features and alternatives * INSTALL: Installation from source code PPrroobblleemm ssoollvviinngg @@ -52,6 +53,7 @@ LLooookkuupp ttaabblleess ((ddaattaabbaasseess)) * LDAP_README: LDAP Howto * LMDB_README: LMDB Howto * MEMCACHE_README: Memcache Howto + * MONGODB_README: MongoDB Howto * MYSQL_README: MySQL Howto * PCRE_README: PCRE Howto * PGSQL_README: PostgreSQL Howto diff --git a/README_FILES/ADDRESS_CLASS_README b/README_FILES/ADDRESS_CLASS_README index 7605aa2..774976e 100644 --- a/README_FILES/ADDRESS_CLASS_README +++ b/README_FILES/ADDRESS_CLASS_README @@ -25,18 +25,23 @@ important for the operation of Postfix. An address class is defined by three items. - * The list of domains that are a member of that address class: for example, - all local domains, or all relay domains. + * The list of domains that are a member of that address class. - * The default delivery transport for that address class. For example, the - local, virtual or relay delivery transport (delivery transports are defined - in master.cf). This helps to keep Postfix configurations simple, by - avoiding the need for explicit routing information in transport maps. + Examples: all local domains, or all relay domains. - * The list of valid recipient addresses for that address class. The Postfix - SMTP server rejects invalid recipients with "User unknown in table". This helps to keep the Postfix queue free of - undeliverable MAILER-DAEMON messages. + * The default delivery transport for domains in that address class. + + Examples: local_transport or relay_transport (these point to services + defined in master.cf). + + Benefit: this avoids the need for explicit routing information in transport + maps. + + * The list of valid recipient addresses for that address class. + + Benefit: the Postfix SMTP server rejects an invalid recipient with "User + unknown in table", and avoids sending a MAILER- + DAEMON message with backscatter spam. WWhhaatt aaddddrreessss ccllaasssseess ddooeess PPoossttffiixx iimmpplleemmeenntt?? @@ -56,11 +61,11 @@ The local domain class. also includes mail for user@[ipaddress] when the IP address is listed with the inet_interfaces or proxy_interfaces parameters. - * Valid recipient addresses are listed with the local_recipient_maps - parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP server - rejects invalid recipients with "User unknown in local recipient table". If - the local_recipient_maps parameter value is empty, then the Postfix SMTP - server accepts any address in the local domain class. + * Valid recipient addresses for those domains are listed with the + local_recipient_maps parameter, as described in LOCAL_RECIPIENT_README. The + Postfix SMTP server rejects invalid recipients with "User unknown in local + recipient table". If the local_recipient_maps parameter value is empty, + then the Postfix SMTP server accepts any address in the local domain class. * The mail delivery transport is specified with the local_transport parameter. The default value is llooccaall::$$mmyyhhoossttnnaammee for delivery with the @@ -69,20 +74,23 @@ The local domain class. The virtual alias domain class. * Purpose: hosted domains where each recipient address is aliased to an - address in a different domain, for example, a local UNIX system account or - a remote address. A virtual alias example is given in the VIRTUAL_README - file. + address in a different domain class, for example, a local UNIX system + account or a remote address. A virtual alias example is given in the + VIRTUAL_README file. * Domain names are listed in virtual_alias_domains. The default value is $virtual_alias_maps for Postfix 1.1 compatibility. - * Valid recipient addresses are listed with the virtual_alias_maps parameter. - The Postfix SMTP server rejects invalid recipients with "User unknown in - virtual alias table". The default value is $virtual_maps for Postfix 1.1 - compatibility. + * Valid recipient addresses for those domains are listed with the + virtual_alias_maps parameter. The Postfix SMTP server rejects invalid + recipients with "User unknown in virtual alias table". The default value is + $virtual_maps for Postfix 1.1 compatibility. + + Note: for historical reasons, virtual_alias_maps apply to recipients in + all domain classes, not only the virtual alias domain class. - * There is no mail delivery transport parameter. Every address must be - aliased to an address in some other domain. + * There is no configurable mail delivery transport. Every address must be + aliased to an address in some other domain class. The virtual mailbox domain class. @@ -93,11 +101,11 @@ The virtual mailbox domain class. * Domain names are listed with the virtual_mailbox_domains parameter. The default value is $virtual_mailbox_maps for Postfix 1.1 compatibility. - * Valid recipient addresses are listed with the virtual_mailbox_maps - parameter. The Postfix SMTP server rejects invalid recipients with "User - unknown in virtual mailbox table". If this parameter value is empty, the - Postfix SMTP server accepts all recipients for domains listed in - $virtual_mailbox_domains. + * Valid recipient addresses for those domains are listed with the + virtual_mailbox_maps parameter. The Postfix SMTP server rejects invalid + recipients with "User unknown in virtual mailbox table". If this parameter + value is empty, the Postfix SMTP server accepts all recipients for domains + listed in $virtual_mailbox_domains. * The mail delivery transport is specified with the virtual_transport parameter. The default value is vviirrttuuaall for delivery with the virtual(8) @@ -113,11 +121,11 @@ The relay domain class. * Domain names are listed with the relay_domains parameter. - * Valid recipient addresses are listed with the relay_recipient_maps - parameter. The Postfix SMTP server rejects invalid recipients with "User - unknown in relay recipient table". If this parameter value is empty, the - Postfix SMTP server accepts all recipients for domains listed with the - relay_domains parameter. + * Valid recipient addresses for those domains are listed with the + relay_recipient_maps parameter. The Postfix SMTP server rejects invalid + recipients with "User unknown in relay recipient table". If this parameter + value is empty, the Postfix SMTP server accepts all recipients for domains + listed with the relay_domains parameter. * The mail delivery transport is specified with the relay_transport parameter. The default value is rreellaayy which is a clone of the smtp(8) diff --git a/README_FILES/ADDRESS_REWRITING_README b/README_FILES/ADDRESS_REWRITING_README index 78237b9..4c24287 100644 --- a/README_FILES/ADDRESS_REWRITING_README +++ b/README_FILES/ADDRESS_REWRITING_README @@ -51,8 +51,7 @@ Topics covered in this document: * Address rewriting when mail is delivered - o Resolve address to destination - o Mail transport switch + o Resolve address to (transport, next-hop destination) o Relocated users table * Address rewriting with remote delivery @@ -131,59 +130,57 @@ this document for the first time, skip forward to "Address rewriting when mail is received". Once you've finished reading the remainder of this document, the table will help you to quickly find what you need. - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - |AAddddrreessss |SSccooppee |DDaaeemmoonn |GGlloobbaall ttuurrnn--oonn |SSeelleeccttiivvee ttuurrnn--ooffff ccoonnttrrooll | - |mmaanniippuullaattiioonn| | |ccoonnttrrooll | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Rewrite | |trivial-|append_at_myorigin, | | - |addresses to|all mail|rewrite |append_dot_mydomain,|local_header_rewrite_clients,| - |standard | |(8) |swap_bangpath, |remote_header_rewrite_domain | - |form | | |allow_percent_hack | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Canonical | |cleanup | |receive_override_options, | - |address |all mail|(8) |canonical_maps |local_header_rewrite_clients,| - |mapping | | | |remote_header_rewrite_domain | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Address | |cleanup | |receive_override_options, | - |masquerading|all mail|(8) |masquerade_domains |local_header_rewrite_clients,| - | | | | |remote_header_rewrite_domain | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Automatic | |cleanup |always_bcc, | | - |BCC |new mail|(8) |sender_bcc_maps, |receive_override_options | - |recipients | | |recipient_bcc_maps | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Virtual |all mail|cleanup |virtual_alias_maps |receive_override_options | - |aliasing | |(8) | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Resolve | |trivial-| | | - |address to |all mail|rewrite |none |none | - |destination | |(8) | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Mail | |trivial-| | | - |transport |all mail|rewrite |transport_maps |none | - |switch | |(8) | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Relocated | |trivial-| | | - |users table |all mail|rewrite |relocated_maps |none | - | | |(8) | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Generic |outgoing| | | | - |mapping |SMTP |smtp(8) |smtp_generic_maps |none | - |table |mail | | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Local alias |local | | | | - |database |mail |local(8)|alias_maps |none | - | |only | | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Local per- |local | | | | - |user |mail |local(8)|forward_path |none | - |.forward |only | | | | - |files | | | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | - |Local catch-|local | | | | - |all address |mail |local(8)|luser_relay |none | - | |only | | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |AAddddrreessss |SSccooppee |DDaaeemmoonn |TTuurrnn--oonn ccoonnttrroollss |TTuurrnn--ooffff ccoonnttrroollss | + |mmaanniippuullaattiioonn| | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Rewrite | |trivial-|append_at_myorigin, | | + |addresses to|all mail|rewrite |append_dot_mydomain, swap_bangpath, |local_header_rewrite_clients,| + |standard | |(8) |allow_percent_hack |remote_header_rewrite_domain | + |form | | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Canonical | |cleanup | |receive_override_options, | + |address |all mail|(8) |canonical_maps |local_header_rewrite_clients,| + |mapping | | | |remote_header_rewrite_domain | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Address | |cleanup | |receive_override_options, | + |masquerading|all mail|(8) |masquerade_domains |local_header_rewrite_clients,| + | | | | |remote_header_rewrite_domain | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Automatic | |cleanup |always_bcc, sender_bcc_maps, | | + |BCC |new mail|(8) |recipient_bcc_maps |receive_override_options | + |recipients | | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Virtual |all mail|cleanup |virtual_alias_maps |receive_override_options | + |aliasing | |(8) | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Resolve | | |local_transport, virtual_transport, | | + |address to | |trivial-|relay_transport, default_transport, | | + |(transport, |all mail|rewrite |relayhost, |content_filter | + |next-hop | |(8) |sender_dependent_relayhost_maps, | | + |destination)| | |sender_dependent_default_transport_maps| | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Relocated | |trivial-| | | + |users table |all mail|rewrite |relocated_maps |none | + | | |(8) | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Generic |outgoing| | | | + |mapping |SMTP |smtp(8) |smtp_generic_maps |none | + |table |mail | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Local alias |local | | | | + |database |mail |local(8)|alias_maps |none | + | |only | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Local per- |local | | | | + |user |mail |local(8)|forward_path |none | + |.forward |only | | | | + |files | | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Local catch-|local | | | | + |all address |mail |local(8)|luser_relay |none | + | |only | | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | AAddddrreessss rreewwrriittiinngg wwhheenn mmaaiill iiss rreecceeiivveedd @@ -492,6 +489,10 @@ transform " Firstname.Lastname " back into UNIX login names, although it seems that local aliases may be a more appropriate vehicle. See the VIRTUAL_README document for an overview of methods to host virtual domains with Postfix. +Note: virtual aliasing (virtual_alias_maps) applies to all recipients: local +(8), virtual, and remote. This is unlike local aliasing (alias_maps) which +applies only to local(8) recipients. + Virtual aliasing is disabled by default. To enable, edit the virtual_alias_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. @@ -537,8 +538,7 @@ manipulations to the trivial-rewrite(8) server. Address manipulations at this stage are: - * Resolve address to destination - * Mail transport switch + * Resolve address to (transport, next-hop destination) * Relocated users table Each Postfix delivery agent tries to deliver the mail to its destination, while @@ -560,49 +560,82 @@ Address manipulations when mail is delivered via the local(8) delivery agent: The remainder of this document presents each address manipulation step in more detail, with specific examples or with pointers to documentation with examples. -RReessoollvvee aaddddrreessss ttoo ddeessttiinnaattiioonn +RReessoollvvee aaddddrreessss ttoo ((ttrraannssppoorrtt,, nneexxtt--hhoopp ddeessttiinnaattiioonn)) The Postfix qmgr(8) queue manager selects new mail from the incoming queue or -old mail from the deferred queue, and asks the trivial-rewrite(8) address -rewriting and resolving daemon where it should be delivered. - -As of version 2.0, Postfix distinguishes four major address classes. Each class -has its own list of domain names, and each class has its own default delivery +old mail from the deferred queue. First it looks for overrides: + + * The REDIRECT action in access(5), header_checks(5) or body_checks(5) + overrides all recipients of the message, and overrides a content_filter + setting, and FILTER action in access(5), header_checks(5) or body_checks + (5). The REDIRECT action was implemented as a short-cut to retaliate for + abuse. + + * A content_filter setting and FILTER action in access(5), header_checks(5) + or body_checks(5) provide their own (transport, next-hop destination) + information. This bypasses all the steps that are described in the + remainder of this section. + +When there is no content filter override, the qmgr(8) queue manager asks the +trivial-rewrite(8) address rewriting and resolving daemon for each recipient +how to deliver it (which message delivery transport) and where to deliver it +(what next-hop destination). + +As of version 2.0, Postfix distinguishes four major domain classes. Each class +has its own list of recipient domain names, and each class has its own delivery method, as shown in the table below. See the ADDRESS_CLASS_README document for the fine details. Postfix versions before 2.0 only distinguish between local delivery and everything else. - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - |DDeessttiinnaattiioonn ddoommaaiinn lliisstt |DDeeffaauulltt ddeelliivveerryy mmeetthhoodd|AAvvaaiillaabbiilliittyy| - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |$mydestination, $inet_interfaces,|$local_transport |Postfix 1.0 | - |$proxy_interfaces | | | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |$virtual_mailbox_domains |$virtual_transport |Postfix 2.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |$relay_domains |$relay_transport |Postfix 2.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |none |$default_transport |Postfix 1.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - -MMaaiill ttrraannssppoorrtt sswwiittcchh - -Once the trivial-rewrite(8) daemon has determined a default delivery method it -searches the optional transport(5) table for information that overrides the -message destination and/or delivery method. Typical use of the transport(5) -table is to send mail to a system that is not connected to the Internet, or to -use a special SMTP client configuration for destinations that have special -requirements. See, for example, the STANDARD_CONFIGURATION_README and -UUCP_README documents, and the examples in the transport(5) manual page. - -Transport table lookups are disabled by default. To enable, edit the -transport_maps parameter in the main.cf file and specify one or more lookup -tables, separated by whitespace or commas. +Note that the table does not match recipients against virtual_alias_domains. +The reason is that all valid recipients in a virtual alias domain must be +aliased to an address in a different domain. All other recipients in a virtual +alias domain are by definition undeliverable, and do not need to be considered +here. -Example: - - /etc/postfix/main.cf: - transport_maps = hash:/etc/postfix/transport + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |DDoommaaiinn ccllaassss |RReecciippiieenntt ddoommaaiinn mmaattcchh |DDeelliivveerryy mmeetthhoodd |AAvvaaiillaabbiilliittyy| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + | |mydestination, | | | + |Local |inet_interfaces, |local_transport |Postfix 1.0 | + | |proxy_interfaces | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |Virtual mailbox|virtual_mailbox_domains|virtual_transport|Postfix 2.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |Relay |relay_domains |relay_transport |Postfix 2.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |Default |none |default_transport|Postfix 1.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + +The delivery methods in the above table may include a next-hop destination in +addition to a delivery transport. This may override the next-hop destination +that is by default taken from the recipient domain. + +Over time, features have been added to override the above transport and/or +next-hop destination information. The following table lists where a transport +or next-hop destination may be taken from, depending on the recipient domain +class. + + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |DDoommaaiinn |TTrraannssppoorrtt ssoouurrcceess ((iinn oorrddeerr ooff |NNeexxtt hhoopp ssoouurrcceess ((iinn oorrddeerr ooff ddeesscceennddiinngg| + |ccllaassss |ddeesscceennddiinngg pprreecceeddeennccee)) |pprreecceeddeennccee)) | + |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Local |transport_maps, local_transport |transport_maps, local_transport, | + | | |recipient domain | + |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |Virtual|transport_maps, virtual_transport |transport_maps, virtual_transport, | + |mailbox| |recipient domain | + |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + | | |transport_maps, relay_transport, | + |Relay |transport_maps, relay_transport |sender_dependent_relayhost_maps, | + | | |relayhost, recipient domain | + |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + | | |transport_maps, | + | |transport_maps, |sender_dependent_default_transport_maps,| + |Default|sender_dependent_default_transport_maps,|default_transport, | + | |default_transport |sender_dependent_relayhost_maps, | + | | |relayhost, recipient domain | + |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | RReellooccaatteedd uusseerrss ttaabbllee @@ -674,6 +707,10 @@ implement distribution lists, or to direct mail for standard aliases such as postmaster to real people. The table can also be used to map "Firstname.Lastname" addresses to login names. +Note: local aliasing (alias_maps) applies only to local(8) recipients. This is +unlike virtual aliasing (virtual_alias_maps) which applies to all recipients: +local(8), virtual, and remote. + Alias lookups are enabled by default. The default configuration depends on the operating system environment, but it is typically one of the following: diff --git a/README_FILES/COMPATIBILITY_README b/README_FILES/COMPATIBILITY_README index 55182b7..aa9e7f6 100644 --- a/README_FILES/COMPATIBILITY_README +++ b/README_FILES/COMPATIBILITY_README @@ -33,17 +33,17 @@ Logged with compatibility_level < 1: * Using backwards-compatible default setting chroot=y -Logged with compatibility_level < 2: - * Using backwards-compatible default setting "smtpd_relay_restrictions = (empty)" + * Using backwards-compatible default setting smtputf8_enable=no + +Logged with compatibility_level < 2: + * Using backwards-compatible default setting mynetworks_style=subnet * Using backwards-compatible default setting relay_domains=$mydestination - * Using backwards-compatible default setting smtputf8_enable=no - Logged with compatibility_level < 3.6: * Using backwards-compatible default setting smtpd_tls_fingerprint_digest=md5 @@ -152,6 +152,34 @@ permanent in main.cf: # ppoossttccoonnff ssmmttppdd__rreellaayy__rreessttrriiccttiioonnss== # ppoossttffiixx rreellooaadd +UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg ssmmttppuuttff88__eennaabbllee==nnoo + +The smtputf8_enable default value has changed from "no" to "yes". With the new +"yes" setting, the Postfix SMTP server rejects non-ASCII addresses from clients +that don't request SMTPUTF8 support, after Postfix is updated from an older +version. The backwards-compatibility safety net is designed to prevent such +surprises. + +As long as the smtputf8_enable parameter is left at its implicit default value, +and the compatibility_level setting is less than 1, Postfix logs a warning each +time an SMTP command uses a non-ASCII address localpart without requesting +SMTPUTF8 support: + + postfix/smtpd[27560]: using backwards-compatible default setting + smtputf8_enable=no to accept non-ASCII sender address + "??@example.org" from localhost[127.0.0.1] + + postfix/smtpd[27560]: using backwards-compatible default setting + smtputf8_enable=no to accept non-ASCII recipient address + "??@example.com" from localhost[127.0.0.1] + +If the address should not be rejected, and the client cannot be updated to use +SMTPUTF8, then the system administrator should make the backwards-compatible +setting "smtputf8_enable = no" permanent in main.cf: + + # ppoossttccoonnff ssmmttppuuttff88__eennaabbllee==nnoo + # ppoossttffiixx rreellooaadd + UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg mmyynneettwwoorrkkss__ssttyyllee==ssuubbnneett The mynetworks_style default value has changed from "subnet" to "host". This @@ -223,34 +251,6 @@ Note: quotes are required as indicated above. Instead of $mydestination, it may be better to specify an explicit list of domain names. -UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg ssmmttppuuttff88__eennaabbllee==nnoo - -The smtputf8_enable default value has changed from "no" to "yes". With the new -"yes" setting, the Postfix SMTP server rejects non-ASCII addresses from clients -that don't request SMTPUTF8 support, after Postfix is updated from an older -version. The backwards-compatibility safety net is designed to prevent such -surprises. - -As long as the smtputf8_enable parameter is left at its implicit default value, -and the compatibility_level setting is less than 1, Postfix logs a warning each -time an SMTP command uses a non-ASCII address localpart without requesting -SMTPUTF8 support: - - postfix/smtpd[27560]: using backwards-compatible default setting - smtputf8_enable=no to accept non-ASCII sender address - "??@example.org" from localhost[127.0.0.1] - - postfix/smtpd[27560]: using backwards-compatible default setting - smtputf8_enable=no to accept non-ASCII recipient address - "??@example.com" from localhost[127.0.0.1] - -If the address should not be rejected, and the client cannot be updated to use -SMTPUTF8, then the system administrator should make the backwards-compatible -setting "smtputf8_enable = no" permanent in main.cf: - - # ppoossttccoonnff ssmmttppuuttff88__eennaabbllee==nnoo - # ppoossttffiixx rreellooaadd - UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg ssmmttppdd__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt==mmdd55 The smtpd_tls_fingerprint_digest default value has changed from "md5" to diff --git a/README_FILES/DATABASE_README b/README_FILES/DATABASE_README index 3fd88c3..f1629e9 100644 --- a/README_FILES/DATABASE_README +++ b/README_FILES/DATABASE_README @@ -28,7 +28,7 @@ Examples of lookup tables that appear often in the Postfix documentation: alias_maps = hash:/etc/postfix/aliases (local aliasing) header_checks = regexp:/etc/postfix/header_checks (content filtering) transport_maps = hash:/etc/postfix/transport (routing table) - virtual_alias_maps = hash:/etc/postfix/virtual (address rewriting) + virtual_alias_maps = hash:/etc/postfix/virtual (virtual aliasing) All Postfix lookup tables store information as (key, value) pairs. This interface may seem simplistic at first, but it turns out to be very powerful. @@ -236,6 +236,9 @@ To find out what database types your Postfix system supports, use the "ppooss mmeemmccaacchhee Memcache database client. Configuration details are given in memcache_table(5). + mmoonnggooddbb (read-only) + MongoDB database client. Configuration details are given in + mongodb_table(5), with examples in MONGODB_README. mmyyssqqll (read-only) MySQL database client. Configuration details are given in mysql_table (5). diff --git a/README_FILES/DEPRECATION_README b/README_FILES/DEPRECATION_README new file mode 100644 index 0000000..87cf247 --- /dev/null +++ b/README_FILES/DEPRECATION_README @@ -0,0 +1,270 @@ +PPoossttffiixx RReeppllaacceemmeennttss ffoorr DDeepprreeccaatteedd FFeeaattuurreess + +------------------------------------------------------------------------------- + +PPuurrppoossee ooff tthhiiss ddooccuummeenntt + +This document describes Postfix features that are deprecated (will be removed) +or that have already been removed. It also has tips for making an existing +Postfix configuration more future-proof. + +Overview: + + * Why deprecate? + * Deprecation process + * Deprecated features + +WWhhyy ddeepprreeccaattee?? + +Sometimes, a Postfix feature needs to be replaced with a different one. To give +an example: + + * The initial Postfix TLS implementation used multiple boolean parameters: + one parameter to enable opportunistic TLS (for example, "smtp_enforce_tls = + yes") and one parameter to enable mandatory TLS (for example, + "smtp_require_tls = yes"). + + * As we added support more features such as fingerprint, dane, and so on, we + decided not to add more boolean parameters. Instead we introduced one + configuration parameter to select from multiple deployment models (for + example, smtp_tls_security_level = may | encrypt | dane, etc...). + +Having both the "old" and "new" way to configure Postfix is convenient for +existing Postfix installations, because their configuration does not break +after an upgrade to a new version. Unfortunately, there are also disadvantages. +Having multiple ways to do similar things is not only confusing for newcomers, +it also makes Postfix harder to change. + +DDeepprreeccaattiioonn pprroocceessss + +The basic process steps are: + + 1. Inform humans that a feature will be removed, and suggest replacements, in + logging and documentation. + + 2. Remove the feature, and update logging and documentation. + +Disclaimer: it has taken 20 years for some features to be removed. This past is +not a guarantee for the future. + +DDeepprreeccaatteedd ffeeaattuurreess + +The table summarizes removed or deprecated features and replacements. Click on +the "obsolete feature" name for a more detailed description. + + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + | |WWaarrnniinngg| | | + |OObbssoolleettee ffeeaattuurree nnaammee |aass |RReemmoovveedd |RReeppllaacceemmeenntt | + | |ooff |iinn vveerrssiioonn| | + | |vveerrssiioonn| | | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |disable_dns_lookups | 3.9 | - |smtp_dns_support_level | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |xxx_use_tls | 3.9 | - |xxx_tls_security_level | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |xxx_enforce_tls | 3.9 | - |xxx_tls_security_level | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |xxx_per_site | 3.9 | - |xxx_policy_maps | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |smtpd_tls_dh1024_param_file| 3.9 | - |do not specify (leave at | + | | | |default) | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |smtpd_tls_eecdh_grade | 3.9 | - |do not specify (leave at | + | | | |default) | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |permit_mx_backup | 3.9 | - |relay_domains | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |check_relay_domains | 2.2 | 3.9 |permit_mynetworks, | + | | | |reject_unauth_destination| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |reject_maps_rbl | 2.1 | 3.9 |reject_rbl_client | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |permit_naked_ip_address | 2.0 | 3.9 |permit_mynetworks, | + | | | |permit_sasl_authenticated| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + +OObbssoolleettee DDNNSS oonn//ooffff ccoonnffiigguurraattiioonn + +The postconf(1) command logs the following: + + * support for parameter "disable_dns_lookups" will be removed; instead, + specify "smtp_dns_support_level" + +Replace obsolete configuration with its replacement: + + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |GGooaall |OObbssoolleettee ccoonnffiigguurraattiioonn |RReeppllaacceemmeenntt | + | | |ccoonnffiigguurraattiioonn | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |To disable DNS lookups|disable_dns_lookups = |smtp_dns_support_level =| + |in the Postfix SMTP/ |yes |disabled | + |LMTP client | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + | | |Leave | + | | |smtp_dns_support_level | + |To enable DNS lookups | |at the implicit default | + |in the Postfix SMTP/ |disable_dns_lookups = no|which is empty, unless | + |LMTP client | |you need a higher | + | | |support level such as | + | | |DNSSEC. | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + +OObbssoolleettee ooppppoorrttuunniissttiicc TTLLSS ccoonnffiigguurraattiioonn + +The postconf(1) command logs one of the following: + + * support for parameter "lmtp_use_tls" will be removed; instead, specify + "lmtp_tls_security_level" + * support for parameter "smtp_use_tls" will be removed; instead, specify + "smtp_tls_security_level" + * support for parameter "smtpd_use_tls" will be removed; instead, specify + "smtpd_tls_security_level" + +There are similarly-named parameters and warnings for postscreen(8) and +tlsproxy(8), but those parameters should rarely be specified by hand. + +Replace obsolete configuration with its replacement: + + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |GGooaall |OObbssoolleettee ccoonnffiigguurraattiioonn|RReeppllaacceemmeenntt ccoonnffiigguurraattiioonn| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |To turn off TLS |xxx_use_tls = no |xxx_security_level = none| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |To turn on opportunistic|xxx_use_tls = yes |xxx_security_level = may | + |TLS | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + +OObbssoolleettee mmaannddaattoorryy TTLLSS ccoonnffiigguurraattiioonn + +The postconf(1) command logs one of the following: + + * support for parameter "lmtp_enforce_tls" will be removed; instead, specify + "lmtp_tls_security_level" + * support for parameter "smtp_enforce_tls" will be removed; instead, specify + "smtp_tls_security_level" + * support for parameter "smtpd_enforce_tls" will be removed; instead, specify + "smtpd_tls_security_level" + +There are similarly-named parameters and warnings for postscreen(8) and +tlsproxy(8), but those parameters should rarely be specified by hand. + +Replace obsolete configuration with its replacement: + + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |GGooaall |OObbssoolleettee ccoonnffiigguurraattiioonn|RReeppllaacceemmeenntt ccoonnffiigguurraattiioonn| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |To turn off mandatory |xxx_enforce_tls = no |xxx_security_level = may | + |TLS | | | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + |To turn on mandatory TLS|xxx_enforce_tls = yes |xxx_security_level = | + | | |encrypt | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | + +OObbssoolleettee TTLLSS ppoolliiccyy ttaabbllee ccoonnffiigguurraattiioonn + +The postconf(1) command logs one of the following: + + * support for parameter "lmtp_tls_per_site" will be removed; instead, specify + "lmtp_tls_policy_maps" + * support for parameter "smtp_tls_per_site" will be removed; instead, specify + "smtp_tls_policy_maps" + +There is similarly-named parameter and warning for tlsproxy(8), but that +parameter should rarely be specified by hand. + +Unfortunately, this is more than a name change: the table format has changed +too, as has the table search process. There is no simple conversion of the +obsolete form to its replacement. + +cchheecckk__rreellaayy__ddoommaaiinnss + +Depending on the Postfix version, the Postfix SMTP daemon logs following +warning: + + * support for restriction "check_relay_domains" has been removed in Postfix + 3.9"; instead, specify "reject_unauth_destination" + * support for restriction "check_relay_domains" will be removed from Postfix; + use "reject_unauth_destination" instead + +This feature was removed because it would relay based on the client domain +name, which is not robust. + +Recommended configuration to prevent an "open relay" problem with the SMTP +service on port 25: + + main.cf: + smtpd_recipient_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination + ...other restrictions... + +Or equivalent in smtpd_relay_restrictions. + +ppeerrmmiitt__mmxx__bbaacckkuupp + +The Postfix version 3.9 and later SMTP daemon logs the following warning: + + * support for restriction "permit_mx_backup" will be removed from Postfix; + instead, specify "relay_domains" + +This feature will be removed because it is too difficult to configure recipient +address validation, making Postfix a source of backscatter bounces. + +To specify the domains that Postfix will provide MX backup service for, see +Configuring Postfix as primary or backup MX host for a remote site. + +rreejjeecctt__mmaappss__rrbbll + +Depending on the Postfix version, the SMTP daemon logs one of the following +warnings: + + * support for restriction "reject_maps_rbl" has been removed in Postfix 3.9"; + instead, specify "reject_rbl_client domain-name" + * support for restriction "reject_maps_rbl" will be removed from Postfix; use + "reject_rbl_client domain-name" instead + +This feature was replaced because "MAPS RBL" is the name of a specific +reputation service. The reject_rbl_client feature provides a superset of the +reject_maps_rbl functionality. + +Recommended configuration: + + main.cf: + smtpd_recipient_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination + reject_rbl_client domain-name + ...other restrictions... + +Where domain-name is the domain name of a DNS reputation service. + +ppeerrmmiitt__nnaakkeedd__iipp__aaddddrreessss + +Depending on the Postfix version, the SMTP daemon logs one of the following +warnings: + + * support for restriction "permit_naked_ip_address" has been removed in + Postfix 3.9"; instead, specify "permit_mynetworks" or + "permit_sasl_authenticated" + * restriction permit_naked_ip_address is deprecated. Use permit_mynetworks or + permit_sasl_authenticated instead + +This feature was removed because it was easy to get a false match when +smtpd_recipient_restrictions was intended to match a remote SMTP client IP +address. + +Recommended configuration: + + main.cf: + smtpd_recipient_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination + reject_rbl_client domain-name + ...other restrictions... + +That is, no restriction on HELO or EHLO syntax. Such restrictions ar rarely +useful nowadays. + diff --git a/README_FILES/INSTALL b/README_FILES/INSTALL index 09d0f80..85ed2cc 100644 --- a/README_FILES/INSTALL +++ b/README_FILES/INSTALL @@ -376,27 +376,29 @@ whistles. Support for third-party databases etc. must be configured when Postfix is compiled. The following documents describe how to build Postfix with support for optional features: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - |OOppttiioonnaall ffeeaattuurree |DDooccuummeenntt |AAvvaaiillaabbiilliittyy| - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |Berkeley DB database |DB_README |Postfix 1.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |LMDB database |LMDB_README |Postfix 2.11| - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |LDAP database |LDAP_README |Postfix 1.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |MySQL database |MYSQL_README |Postfix 1.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |Perl compatible regular expression|PCRE_README |Postfix 1.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |PostgreSQL database |PGSQL_README |Postfix 2.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |SASL authentication |SASL_README |Postfix 1.0 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |SQLite database |SQLITE_README|Postfix 2.8 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | - |STARTTLS session encryption |TLS_README |Postfix 2.2 | - |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + |OOppttiioonnaall ffeeaattuurree |DDooccuummeenntt |AAvvaaiillaabbiilliittyy| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |Berkeley DB database |DB_README |Postfix 1.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |LMDB database |LMDB_README |Postfix 2.11| + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |LDAP database |LDAP_README |Postfix 1.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |MongoDB database |MONGODB_README|Postfix 3.9 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |MySQL database |MYSQL_README |Postfix 1.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |Perl compatible regular expression|PCRE_README |Postfix 1.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |PostgreSQL database |PGSQL_README |Postfix 2.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |SASL authentication |SASL_README |Postfix 1.0 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |SQLite database |SQLITE_README |Postfix 2.8 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | + |STARTTLS session encryption |TLS_README |Postfix 2.2 | + |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ | Note: IP version 6 support is compiled into Postfix on operating systems that have IPv6 support. See the IPV6_README file for details. diff --git a/README_FILES/LOCAL_RECIPIENT_README b/README_FILES/LOCAL_RECIPIENT_README index ea4ce25..c8b97bd 100644 --- a/README_FILES/LOCAL_RECIPIENT_README +++ b/README_FILES/LOCAL_RECIPIENT_README @@ -30,7 +30,7 @@ addresses of local recipients. A recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local username or address is not listed in $local_recipient_maps, then the Postfix SMTP server will reject the address with "User unknown in local recipient -table". +table". Other Postfix interfaces may still accept an "unknown" recipient. The default setting, shown below, assumes that you use the default Postfix local(8) delivery agent for local delivery, where recipients are either UNIX diff --git a/README_FILES/MAILLOG_README b/README_FILES/MAILLOG_README index 6f8fead..75fa4b5 100644 --- a/README_FILES/MAILLOG_README +++ b/README_FILES/MAILLOG_README @@ -30,8 +30,14 @@ problems for systemd-based systems. 2. Configure Postfix to write logging, to, for example, /var/log/postfix.log. See also the "Logfile rotation" section below for logfile management. + In the example below, specifying maillog_file_permissions is optional + (Postfix 3.9 and later). The default value is 0600, i.e., only the super- + user can access the file; the value 0644 also adds 'group' and 'other' read + access. + # postfix stop # postconf maillog_file=/var/log/postfix.log + # postconf maillog_file_permissions=0644 # (Postfix 3.9 and later) # postfix start By default, the logfile name must start with "/var" or "/dev/stdout" (the @@ -71,6 +77,10 @@ implements the following steps: * After a brief pause, compress the old logfile. The compression program is configured with the maillog_file_compressor parameter (default: gzip). + * The next time it logs an event, postlogd(8) will create a new logfile, with + permissions specified with the maillog_file_permissions parameter (default: + 0600). + Notes: * This command will not rotate a logfile with a pathname under the /dev diff --git a/README_FILES/MILTER_README b/README_FILES/MILTER_README index 4ace868..7d9e938 100644 --- a/README_FILES/MILTER_README +++ b/README_FILES/MILTER_README @@ -392,9 +392,9 @@ ccoommmmaa wwiitthhiinn aa vvaalluuee oorr aarroouunndd DDiiffffeerreenntt sseettttiinnggss ffoorr ddiiffffeerreenntt SSMMTTPP cclliieennttss The smtpd_milter_maps feature supports different Milter settings for different -client IP addresses. Lookup results override the the global smtpd_milters -setting, and have the same syntax. For example, to disable Milter settings for -local address ranges: +client IP addresses. Lookup results override the global smtpd_milters setting, +and have the same syntax. For example, to disable Milter settings for local +address ranges: /etc/postfix/main.cf: smtpd_milter_maps = cidr:/etc/postfix/smtpd_milter_map diff --git a/README_FILES/MONGODB_README b/README_FILES/MONGODB_README new file mode 100644 index 0000000..c8b8fc6 --- /dev/null +++ b/README_FILES/MONGODB_README @@ -0,0 +1,188 @@ +PPoossttffiixx MMoonnggooDDBB HHoowwttoo + +------------------------------------------------------------------------------- + +MMoonnggooDDBB SSuuppppoorrtt iinn PPoossttffiixx + +Postfix can use MongoDB as a source for any of its lookups: aliases(5), virtual +(5), canonical(5), etc. This allows you to keep information for your mail +service in a replicated noSQL database with fine-grained access controls. By +not storing it locally on the mail server, the administrators can maintain it +from anywhere, and the users can control whatever bits of it you think +appropriate. You can have multiple mail servers using the same information, +without the hassle and delay of having to copy it to each. + +Topics covered in this document: + + * Building Postfix with MongoDB support + * Configuring MongoDB lookups + * Example: virtual alias maps + * Example: Mailing lists + * Example: MongoDB projections + * Feedback + * Credits + +BBuuiillddiinngg PPoossttffiixx wwiitthh MMoonnggooDDBB ssuuppppoorrtt + +These instructions assume that you build Postfix from source code as described +in the INSTALL document. Some modification may be required if you build Postfix +from a vendor-specific source package. + +The Postfix MongoDB client requires the mmoonnggoo--cc--ddrriivveerr library. This can be +built from source code from the mongod-c project, or this can be installed as a +binary package from your OS distribution, typically named mmoonnggoo--cc--ddrriivveerr, +mmoonnggoo--cc--ddrriivveerr--ddeevveell or lliibbmmoonnggoocc--ddeevv. Installing the mongo-c-driver library +may also install lliibbbbssoonn as a dependency. + +To build Postfix with mongodb map support, add to the CCARGS environment +variable the options -DHAS_MONGODB and -I for the directory containing the +mongodb headers, and specify the AUXLIBS_MONGODB with the libmongoc and libbson +libraries, for example: + + % make tidy + % make -f Makefile.init makefiles \ + CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \ + -I/usr/include/libbson-1.0" \ + AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0" + +The 'make tidy' command is needed only if you have previously built Postfix +without MongoDB support. + +If your MongoDB shared library is in a directory that the RUN-TIME linker does +not know about, add a "-Wl,-R,/path/to/directory" option after "-lbson-1.0". +Then, just run 'make'. + +CCoonnffiigguurriinngg MMoonnggooDDBB llooookkuuppss + +In order to use MongoDB lookups, define a MongoDB source as a table lookup in +main.cf, for example: + + alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf + +The file /etc/postfix/mongo-aliases.cf can specify a number of parameters. For +a complete description, see the mongodb_table(5) manual page. + +EExxaammppllee:: vviirrttuuaall((55)) aalliiaass mmaappss + +Here's a basic example for using MongoDB to look up virtual(5) aliases. Assume +that in main.cf, you have: + + virtual_alias_maps = hash:/etc/postfix/virtual_aliases, + proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf + +and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have: + + uri = mongodb+srv://user_name:password@some_server + dbname = mail + collection = mailbox + query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], + "active": 1} + result_attribute = username + +This example assumes mailbox names are stored in a MongoDB backend, in a format +like: + + { "username": "user@example.com", + "alias": [ + {"address": "admin@example.com"}, + {"address": "abuse@example.com"} + ], + "active": 1 + } + +Upon receiving mail for "admin@example.com" that isn't found in the /etc/ +postfix/virtual_aliases database, Postfix will search the MongoDB server/ +cluster listening at port 27017 on some_server. It will connect using the +provided credentials, and search for any entries whose username is, or alias +field has "admin@example.com". It will return the username attribute of those +found, and build a list of their email addresses. + +Notes: + + * As with pprroojjeeccttiioonn (see below), the Postfix mongodb client automatically + removes the top-level '_id' field from a result_attribute result. + + * The Postfix mongodb client will only parse result fields with data types + UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, with a warning + in the logs. + +EExxaammppllee:: MMaaiilliinngg lliissttss + +When it comes to mailing lists, one way of implementing one would be as below: + + { "name": "dev@example.com", "active": 1, "address": + [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] } + +using the filter below, will result in a comma separated string with all email +addresses in this list. + + query_filter = {"name": "%s", "active": 1} + result_attribute = address + +Notes: + + * As with pprroojjeeccttiioonn (see below), the Postfix mongodb client automatically + removes the top-level '_id' field from a result_attribute result. + + * The Postfix mongodb client will only parse result fields with data types + UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, with a warning + in the logs. + +EExxaammppllee:: aaddvvaanncceedd pprroojjeeccttiioonnss + +This module also supports the use of more complex MongoDB projections. There +may be some use cases where operations such as concatenation are necessary to +be performed on the data retrieved from the database. Although it is encouraged +to keep the database design simple enough so this is not necessary, postfix +supports the use of MongoDB projections to achieve the goal. + +Consider the example below: + + { "username": "user@example.com", + "local_part": "user", + "domain": "example.com", + "alias": [ + {"address": "admin@example.com"}, + {"address": "abuse@example.com"} + ], + "active": 1 + } + +virtual_mailbox_maps can be created using below parameters in a mongodb:/etc/ +postfix/mongo-virtual-mailboxes.cf file: + + uri = mongodb+srv://user_name:password@some_server + dbname = mail + collection = mailbox + query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], + "active": 1} + projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} } + +This will return 'example.com/user' path built from the database fields. + +A couple of considerations when using projections: + + * As with rreessuulltt__aattttrriibbuuttee, the Postfix mongodb client automatically removes + the top-level '_id' field from a projection result. + + * The Postfix mongodb client will only parse fields with data types UTF8, + INT32, INT64 and ARRAY. Other fields will be ignored, with a warning in the + logs. It is suggested to exclude any unnecessary fields when using a + projection. + +FFeeeeddbbaacckk + +If you have questions, send them to postfix-users@postfix.org. Please include +relevant information about your Postfix setup: MongoDB-related output from +postconf, which libraries you built with, and such. If your question involves +your database contents, please include the applicable bits of some database +entries. + +CCrreeddiittss + + * Stephan Ferraro (Aionda GmbH) implemented an early version of the Postfix + MongoDB client. + * Hamid Maadani (Dextrous Technologies, LLC) added support for projections + and %letter interpolation, and added documentation. + * Wietse Venema adopted and restructured the code and documentation. + diff --git a/README_FILES/POSTSCREEN_README b/README_FILES/POSTSCREEN_README index 9467e68..5b4d200 100644 --- a/README_FILES/POSTSCREEN_README +++ b/README_FILES/POSTSCREEN_README @@ -78,7 +78,7 @@ Zombies have challenges too: they have only a limited amount of time to deliver spam before their IP address becomes denylisted. To speed up spam deliveries, zombies make compromises in their SMTP protocol implementation. For example, they speak before their turn, or they ignore responses from SMTP servers and -continue sending mail even when the server tells them to go away. +continue sending commands even when the server tells them to go away. postscreen(8) uses a variety of measurements to recognize zombies. First, postscreen(8) determines if the remote SMTP client IP address is denylisted. @@ -114,7 +114,7 @@ clients. QQuuiicckk tteessttss bbeeffoorree eevveerryytthhiinngg eellssee -Before engaging in SMTP-level tests. postscreen(8) queries a number of local +Before engaging in SMTP-level tests, postscreen(8) queries a number of local deny and allowlists. These tests speed up the handling of known clients. * Permanent allow/denylist test diff --git a/README_FILES/TLS_README b/README_FILES/TLS_README index e7fd259..5e63554 100644 --- a/README_FILES/TLS_README +++ b/README_FILES/TLS_README @@ -1726,73 +1726,109 @@ describe the corresponding table syntax: nnoonnee No TLS. No additional attributes are supported at this level. mmaayy - Opportunistic TLS. The optional "ciphers", "exclude" and "protocols" - attributes (available for opportunistic TLS with Postfix >= 2.6) override - the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols" - configuration parameters. At this level and higher, the optional - "servername" attribute (available with Postfix >= 3.4) overrides the global - "smtp_tls_servername" parameter, enabling per-destination configuration of - the SNI extension sent to the remote SMTP server. + Opportunistic TLS. The optional "ciphers", "exclude", and "protocols" + attributes (available for opportunistic TLS with Postfix >= 2.6) and + "connection_reuse" attribute (Postfix >= 3.4) override the + "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols", and + "smtp_tls_connection_reuse" configuration parameters. At this level and + higher, the optional "servername" attribute (available with Postfix >= 3.4) + overrides the global "smtp_tls_servername" parameter, enabling per- + destination configuration of the SNI extension sent to the remote SMTP + server. The optional "enable_rpk" attribute (Postfix >= 3.9) overrides the + main.cf smtp_tls_enable_rpk parameter. When opportunistic TLS handshakes + fail, Postfix retries the connection with TLS disabled. This allows mail + delivery to sites with non-interoperable TLS implementations. eennccrryypptt Mandatory encryption. Mail is delivered only if the remote SMTP server offers STARTTLS and the TLS handshake succeeds. At this level and higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute - overrides the main.cf smtp_tls_mandatory_ciphers parameter, and the - optional "exclude" attribute (Postfix >= 2.6) overrides the main.cf - smtp_tls_mandatory_exclude_ciphers parameter. + overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional + "exclude" attribute (Postfix >= 2.6) overrides the main.cf + smtp_tls_mandatory_exclude_ciphers parameter, and the optional + "connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf + smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute + (Postfix >= 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. ddaannee Opportunistic DANE TLS. The TLS policy for the destination is obtained via TLSA records in DNSSEC. If no TLSA records are found, the effective security level used is may. If TLSA records are found, but none are usable, the effective security level is encrypt. When usable TLSA records are - obtained for the remote SMTP server, SSLv2+3 are automatically disabled - (see smtp_tls_mandatory_protocols), and the server certificate must match - the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is - available with Postfix 2.11 and later. + obtained for the remote SMTP server, the server certificate must match the + TLSA records (and the SNI name is unconditionally set to the TLSA base + domain). RFC 7672 (DANE) TLS authentication and DNSSEC support is available + with Postfix 2.11 and later. The optional "connection_reuse" attribute + (Postfix >= 3.4) overrides the main.cf smtp_tls_connection_reuse parameter. + When the effective security level used is may, the optional "ciphers", + "exclude", and "protocols" attributes (Postfix >= 2.6) override the + "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", and "smtp_tls_protocols" + configuration parameters. When the effective security level used is + encrypt, the optional "ciphers", "exclude", and "protocols" attributes + (Postfix >= 2.6) override the "smtp_tls_mandatory_ciphers", + "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" + configuration parameters. ddaannee--oonnllyy Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA records in DNSSEC. If no TLSA records are found, or none are usable, no connection is made to the server. When usable TLSA records are obtained for - the remote SMTP server, SSLv2+3 are automatically disabled (see - smtp_tls_mandatory_protocols), and the server certificate must match the - TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is - available with Postfix 2.11 and later. + the remote SMTP server, the server certificate must match the TLSA records. + RFC 7672 (DANE) TLS authentication and DNSSEC support is available with + Postfix 2.11 and later. The optional "ciphers", "exclude", and "protocols" + attributes (Postfix >= 2.6) override the "smtp_tls_mandatory_ciphers", + "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" + configuration parameters. The optional "connection_reuse" attribute + (Postfix >= 3.4) overrides the main.cf smtp_tls_connection_reuse parameter. ffiinnggeerrpprriinntt Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted Certification Authorities. The certificate trust chain, expiration date, ... are not checked. Instead, the - optional mmaattcchh attribute, or else the main.cf - ssmmttpp__ttllss__ffiinnggeerrpprriinntt__cceerrtt__mmaattcchh parameter, lists the server certificate - fingerprints or public key fingerprints (Postfix 2.9 and later). The digest - algorithm used to calculate fingerprints is selected by the - ssmmttpp__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt parameter. Multiple fingerprints can be - combined with a "|" delimiter in a single match attribute, or multiple - match attributes can be employed. The ":" character is not used as a - delimiter as it occurs between each pair of fingerprint (hexadecimal) - digits. + optional "match" attribute, or else the main.cf + ssmmttpp__ttllss__ffiinnggeerrpprriinntt__cceerrtt__mmaattcchh parameter, lists the certificate + fingerprints or the public key fingerprints (Postfix 2.9 and later) of + acceptable server certificates. The digest algorithm used to calculate the + fingerprint is selected by the ssmmttpp__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt parameter. + Multiple fingerprints can be combined with a "|" delimiter in a single + match attribute, or multiple match attributes can be employed. The ": + " character is not used as a delimiter as it occurs between each pair of + fingerprint (hexadecimal) digits. The optional "ciphers", "exclude", and + "protocols" attributes (Postfix >= 2.6) override the + "smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and + "smtp_tls_mandatory_protocols" configuration parameters. The optional + "connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf + smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute + (Postfix >= 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. vveerriiffyy Mandatory server certificate verification. Mail is delivered only if the - TLS handshake succeeds, if the remote SMTP server certificate can be - validated (not expired or revoked, and signed by a trusted Certification - Authority), and if the server certificate name matches the optional "match" - attribute (or the main.cf smtp_tls_verify_cert_match parameter value when - no optional "match" attribute is specified). With Postfix >= 2.11 the + TLS handshake succeeds, the remote SMTP server certificate chain can be + validated, and a DNS name in the certificate matches the specified match + criteria. At this security level, DNS MX lookups are presumed to be secure + enough, and the name verified in the server certificate is potentially + obtained via unauthenticated DNS MX lookups. The server certificate name + must match either the optional "match" attribute, or else the main.cf + smtp_tls_verify_cert_match parameter value. With Postfix >= 2.11 the "tafile" attribute optionally modifies trust chain verification in the same manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be specified multiple times to load multiple trust-anchor - files. + files. The optional "connection_reuse" attribute (Postfix >= 3.4) overrides + the main.cf smtp_tls_connection_reuse parameter. sseeccuurree Secure certificate verification. Mail is delivered only if the TLS - handshake succeeds, and DNS forgery resistant remote SMTP certificate - verification succeeds (not expired or revoked, and signed by a trusted - Certification Authority), and if the server certificate name matches the - optional "match" attribute (or the main.cf smtp_tls_secure_cert_match - parameter value when no optional "match" attribute is specified). With - Postfix >= 2.11 the "tafile" attribute optionally modifies trust chain - verification in the same manner as the "smtp_tls_trust_anchor_file" - parameter. The "tafile" attribute may be specified multiple times to load - multiple trust-anchor files. + handshake succeeds, the remote SMTP server certificate chain can be + validated, and a DNS name in the certificate matches the specified match + criteria. At this security level, DNS MX lookups, though potentially used + to determine the candidate next-hop gateway IP addresses, are nnoott presumed + to be secure enough for TLS peername verification. Instead, the default + name verified in the server certificate is obtained directly from the next- + hop, or is explicitly specified via the optional "match" attribute which + overrides the main.cf smtp_tls_secure_cert_match parameter. The optional + "ciphers", "exclude", and "protocols" attributes (Postfix >= 2.6) override + the "smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and + "smtp_tls_mandatory_protocols" configuration parameters. With Postfix >= + 2.11 the "tafile" attribute optionally modifies trust chain verification in + the same manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile" + attribute may be specified multiple times to load multiple trust-anchor + files. The optional "connection_reuse" attribute (Postfix >= 3.4) overrides + the main.cf smtp_tls_connection_reuse parameter. Notes: * The "match" attribute is especially useful to verify TLS certificates for diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 0a23bf8..6d32de2 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,19 +1,19 @@ -This is the Postfix 3.8 stable release. +This is the Postfix 3.9 stable release. -The stable Postfix release is called postfix-3.8.x where 3=major -release number, 8=minor release number, x=patchlevel. The stable +The stable Postfix release is called postfix-3.9.x where 3=major +release number, 9=minor release number, x=patchlevel. The stable release never changes except for patches that address bugs or emergencies. Patches change the patchlevel and the release date. New features are developed in snapshot releases. These are called -postfix-3.9-yyyymmdd where yyyymmdd is the release date (yyyy=year, +postfix-3.10-yyyymmdd where yyyymmdd is the release date (yyyy=year, mm=month, dd=day). Patches are never issued for snapshot releases; instead, a new snapshot is released. The mail_release_date configuration parameter (format: yyyymmdd) specifies the release date of a stable release or snapshot release. -If you upgrade from Postfix 3.6 or earlier, please read RELEASE_NOTES-3.7 +If you upgrade from Postfix 3.7 or earlier, please read RELEASE_NOTES-3.8 before proceeding. Dual license @@ -26,32 +26,142 @@ now also distributed with the more recent Eclipse Public License license of their choice. Those who are more comfortable with the IPL can continue with that license. -Incompatibility with Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24 -============================================================== +Topics in this document +----------------------- +- changes that are less visible +- database support +- envid support +- feature deprecation +- mime conversion +- protocol compliance +- security +- tls support -Improvements for outbound SMTP smuggling defense: +Changes that are less visible +----------------------------- -- With "cleanup_replace_stray_cr_lf = yes" (the default), the cleanup - daemon replaces each stray or character in message - content with a space character. The replacement happens before - any other content management (header/body_checks, Milters, etc). +The documentation has been updated to address many questions +that were asked on the postfix-users mailing list. - This prevents outbound SMTP smuggling, where an attacker uses - Postfix to send email containing a non-standard End-of-DATA - sequence, to exploit inbound SMTP smuggling at a vulnerable remote - SMTP server. +More unit tests to make Postfix future-proof. Wietse is now looking +into migrating unit tests to Google test, because other people are +familiar with that framework, than with a Postfix-specific one. - This also improves the remote evaluation of Postfix-added DKIM - and other signatures, as the evaluation result will not depend - on how a remote email server handles stray or characters. +Major changes - database support +-------------------------------- + +[Feature 20240208] MongoDB client support, contributed by Hamid +Maadani, based on earlier code by Stephan Ferraro. For build and +usage instructions see MONGODB_README and mongodb_table(5). + +[Feature 20240129] In the mysql: and pgsql: clients, the hard-coded +idle and retry timer settings are now configurable. Details are in +the updated mysql_table(5) and pgsql_table(5) manpages. + +[Incompat 20230903] The MySQL client no longer supports MySQL +versions < 4.0. MySQL version 4.0 was released in 2003. + +[Incompat 20230419] The MySQL client default characterset is now +configurable with the "charset" configuration file attribute. The +default is "utf8mb4", consistent with the MySQL 8.0 built-in default, +but different from earlier MySQL versions where the built-in default +was "latin1". + +Major changes - envid support +----------------------------- + +[Feature 20230901] The local(8) delivery agent exports an ENVID +environment variable with the RFC 3461 envelope ID if available. + +The pipe(8) delivery agent supports an ${envid} command-line attribute +that expands to the RFC 3461 envelope ID if available. + +Major changes - feature deprecation +----------------------------------- + +[Incompat 20240218] The new document DEPRECATION_README covers +features that have been removed and that will be removed in the +future, with suggestions how to migrate. + +The Postfix SMTP server logs a warning when "permit_mx_backup" is +used (support for restriction "permit_mx_backup" will be removed +from Postfix; instead, use "relay_domains"). File: smtpd/smtpd_check.c. + +The postconf command logs a warning when the following parameters +are specified in main.cf or master.cf: xxx_use_tls, xxx_enforce_tls +(use the corresponding xxx_security_level setting instead); +xxx_per_site (use the corresponding xxx_policy_maps setting instead); +disable_dns_lookups (use smtp_dns_support_level instead); +smtpd_tls_dh1024_param_file, smtpd_tls_eecdh_grade (do not specify, +leave at default). These warning are silenced with the "postconf +-q". + +[Incompat 20240218] The Postfix SMTP server now logs that +permit_naked_ip_address, reject_maps_rbl, and check_relay_domains +have been removed and suggests a replacement. These features have +been logging deprecation warnings since 2005 or earlier, and were +removed from Postfix documentation in 2004. + +Major changes - mime conversion +------------------------------- + +[Feature 20230901] New parameter force_mime_input_conversion (default: +no) to convert body content that claims to be 8-bit into quoted-printable, +before header_checks, body_checks, Milters, and before after-queue +content filters. This feature does not affect messages that are +sent into smtpd_proxy_filter. + +The typical use case is an MTA that applies this conversion before +signing outbound messages, so that the signatures will remain valid +when a message is later handled by an MTA that does not announce +8BITMIME support, or when a message line exceeds the SMTP length +limit. + +Major changes - protocol compliance +----------------------------------- + +[Incompat 20240206] In message headers, Postfix now formats numerical +days as two-digit days, i.e. days 1-9 have a leading zero instead +of a leading space. This change was made because the RFC 5322 date +and time specification recommends (i.e. SHOULD) that a single space +be used in each place that FWS appears. This change avoids a breaking +change in the date string length. + +Major changes - security +------------------------ + +[Incompat 20240226] The Postfix DNS client now limits the total +size of DNS lookup results to 100 records; it drops the excess +records, and logs a warning. This limit is 20x larger than the +number of server addresses that the Postfix SMTP client is willing +to consider when delivering mail, and is far below the number of +records that could cause a tail recursion crash in dns_rr_append() +as reported by Toshifumi Sakaguchi. + +This change introduces a similar limit on the number of DNS requests +that a check_*_*_access restriction can make. + +[Incompat 20240110] With "cleanup_replace_stray_cr_lf = yes" (the +default), the cleanup daemon replaces each stray or +character in message content with a space character. The replacement +happens before any other content management (header/body_checks, +Milters, etc). + +This prevents outbound SMTP smuggling, where an attacker uses Postfix +to send email containing a non-standard End-of-DATA sequence, to +exploit inbound SMTP smuggling at a vulnerable remote SMTP server. + +This also improves the remote evaluation of Postfix-added DKIM and +other signatures, as the evaluation result will not depend on how +a remote email server handles stray or characters. This feature applies to all email that Postfix locally or remotely sends out. It is not allowlisted based on client identity. -Major changes with Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24 -============================================================ +[Feature 20240118] This updates Postfix fixes for inbound SMTP smuggling +attacks. For background, see https://www.postfix.org/smtp-smuggling.html -Improvements for inbound SMTP smuggling defense: +This will be back ported to Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24. - Better compatibility: the recommended setting "smtpd_forbid_bare_newline = normalize" requires the standard End-of-DATA sequence @@ -124,120 +234,76 @@ Alternative settings: # 10.0.0.0/24 chunking, silent-discard # smtpd_discard_ehlo_keywords = chunking, silent-discard -Major changes with Postfix 3.8.1 -================================ - -Security: the Postfix SMTP server optionally disconnects remote -SMTP clients that violate RFC 2920 (or 5321) command pipelining +[Incompat 20230603] the Postfix SMTP server by default disconnects +remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. The server replies with "554 5.5.0 Error: SMTP protocol synchronization" and logs the unexpected remote SMTP client input. -Specify "smtpd_forbid_unauth_pipelining = yes" to enable. This -feature is enabled by default in Postfix 3.9 and later. - -Workaround to limit collateral damage from OS distributions that -crank up security to 11, increasing the number of plaintext email -deliveries. This introduces basic OpenSSL configuration file support, -with two new parameters "tls_config_file" and "tls_config_name". -Details are in the postconf(5) manpage under "tls_config_file" and -"tls_config_name". - -Major changes - documentation and code cleanup ----------------------------------------------- - -There are numerous small fixes to Postfix documentation, and small -code-health changes that should not affect documented behavior but -may improve Postfix behavior for malformed input, or that make -Postfix easier to maintain. See the HISTORY file for details. +Specify "smtpd_reject_unauth_pipelining = no" to disable. -Major changes - SRV support +Major changes - tls support --------------------------- -[Feature 20230214] Support to look up DNS SRV records in the Postfix -SMTP/LMTP client, Based on code by Tomas Korbar (Red Hat). - -For example, with "use_srv_lookup = submission" and "relayhost = -example.com:submission", the Postfix SMTP client will look up DNS -SRV records for _submission._tcp.example.com, and will relay email -through the hosts and ports that are specified with those records. - -See https://www.postfix.org/postconf.5.html#use_srv_lookup for more -details, including how to selectively use SRV in a configuration -that connects to multiple ISP accounts. - -SRV support may also be useful inside a cloud-based infrastructure -when Postfix needs to deliver mail to services that run on a -dynamically-allocated port. - -Major changes - TLS support ---------------------------- - -[Incompat 20230304] This introduces the following changes: - -- Postfix treats the "export" and "low" cipher grade settings as - "medium". The "export" and "low" grades are no longer supported - in OpenSSL 1.1.1, the minimum version that Postfix requires. - -- Postfix default settings now exclude the following deprecated or - unused ciphers (SEED, IDEA, 3DES, RC2, RC4, RC5), digest (MD5), - key exchange algorithms (DH, ECDH), and public key algorithm - (DSS). - -[Feature 20230108] New configuration parameter tls_ffdhe_auto_groups -for finite-field Diffie-Hellman ephemeral (FFDHE) support in TLS -1.3 with OpenSSL 3.0. - -Major changes - attack resistance ---------------------------------- - -[Feature 20240312] the Postfix SMTP server can now aggregate -smtpd_client_*_rate and smtpd_client_*_count statistics by network -block, as specified with smtpd_client_ipv4_prefix_length (default -32, no aggregation) and smtpd_client_ipv6_prefix_length (default -84, aggregation by /84 network blocks). The latter raises the bar -for a memory exhaustion attack. - -[Feature 20221023] Unconditionally disable a CPU resource attack -requesting TLS renegotiation. There's no good reason to support -this in the middle of an SMTP connection. - -Major changes - bit rot ------------------------ - -[Incompat 20221228] Postfix documentation and code have been converted -to use "grep -E" and "grep -F" instead of the historical forms -"egrep" and "fgrep". To build Postfix on a system that supports -only the historical forms, run the script auxiliary/fix-grep/fix-grep.sh -to revert this change. - -Major changes - configuration checks ------------------------------------- - -[Feature 20240406] The postconf command now warns for #comment in -or after a Postfix parameter value. Postfix programs do not support -#comment after other text, and treat that as input. - -Major changes - database support --------------------------------- - -[Incompat 20220509] The PostgreSQL client encoding is now configurable -with the "encoding" Postfix configuration file attribute. The default -is "UTF8". Previously the encoding was hard-coded as "LATIN1". - -Major changes - logging ------------------------ - -[Incompat 20230308] The postfix(1) and postlog(1) commands now -produce stderr logging even when stderr is not connected to a -terminal. This eliminates an inconsistency, and makes these programs -easier to use in some automated procedures. The canonical example -is to capture output from "postmulti -p status" to figure out which -instances are or are not running. - -Major changes - source code organization ----------------------------------------- - -[Incompat 20220507] Most global/mkmap*.[hc] files are moved to the -util directory; only global/mkmap_proxy.* remains. The old file -organization was designed before support for dynamically-loadable -databases was added, and that code suffered from complexity. - +[Feature 20230807] Optional Postfix TLS support to request an RFC7250 +raw public key instead of an X.509 public-key certificate. The +configuration settings for raw key public support will be ignored +when there is no raw public key support in the local TLS implementation +(i.e. Postfix with OpenSSL versions before 3.2). + +- With "smtpd_tls_enable_rpk = yes", the Postfix SMTP server will + request that a remote SMTP client sends an RFC7250 raw public key + instead of an X.509 certificate when asking for or requiring TLS + client authentication. The Postfix SMTP server will still accept + a client public-key certificate instead of a public key. + +- With "smtp_tls_enable_rpk = yes" (or "enable_rpk = yes" in an + smtp policy table) at the security levels "may", "encrypt" or + "fingerprint", the Postfix SMTP client will request that a remote + SMTP server sends an RFC7250 raw public key instead of an X.509 + certificate. The Postfix SMTP client will still accept a server + public key certificate instead of a public key. + +- At the "secure" and "verify" security level, the Postfix SMTP + client will ignore smtp_tls_enable_rpk or enable_rpk settings, + because these levels require a server certificate. + +- At the "dane" and "dane-only" security levels, the Postfix SMTP + client will ignore smtp_tls_enable_rpk or enable_rpk settings, + and will request that a remote SMTP server sends an RFC7250 raw + public key instead of an X.509 certificate when all valid TLSA + records specify only server public keys (no certificates). The + Postfix SMTP client will still accept a server public key + certificate. + +- The Postfix SMTP client and server always send a raw public key + instead of a certificate, if solicited by the remote SMTP peer + and the local TLS implementation supports raw public keys. + +- If a remote SMTP client sends a server name indication with an + SNI TLS extension, and tls_server_sni_maps is configured, the + Postfix SMTP server will extract a raw public key from the indicated + certificate. + +Caution: enabling Postfix raw key support will break authentication +based on certificate fingerprints in check_ccert_access or +smtp_tls_policy_maps, when a remote peer's TLS implementation starts +to send a raw public key instead of a certificate. The solution is +to always use public key fingerprint patterns; these will match not +only a "raw" public key, but also the public key in a certificate. + +To detect such problems before they happen, the Postfix SMTP server +will log a warning when it requests an RFC7250 raw public key instead +of an X.509 certificate, the remote peer sends a certificate instead +of a public key, and check_ccert_access has a matching fingerprint +for the certificate but not for the public key in that certificate. +There is no corresponding warning from the Postfix SMTP client. + +For instructions to generate public-key fingerprints, see the +postconf(5) man pages for smtp_tls_enable_rpk and smtpd_tls_enable_rpk. + +[Feature 20230522] Preliminary support for OpenSSL configuration +files, primarily OpenSSL 1.1.1b and later. This introduces two new +parameters "tls_config_file" and "tls_config_name", which can be +used to limit collateral damage from OS distributions that crank +up security to 11, increasing the number of plaintext email deliveries. +Details are in the postconf(5) manpage under "tls_config_file" and +"tls_config_name". diff --git a/RELEASE_NOTES-3.8 b/RELEASE_NOTES-3.8 new file mode 100644 index 0000000..2944830 --- /dev/null +++ b/RELEASE_NOTES-3.8 @@ -0,0 +1,128 @@ +This is the Postfix 3.8 stable release. + +The stable Postfix release is called postfix-3.8.x where 3=major +release number, 8=minor release number, x=patchlevel. The stable +release never changes except for patches that address bugs or +emergencies. Patches change the patchlevel and the release date. + +New features are developed in snapshot releases. These are called +postfix-3.9-yyyymmdd where yyyymmdd is the release date (yyyy=year, +mm=month, dd=day). Patches are never issued for snapshot releases; +instead, a new snapshot is released. + +The mail_release_date configuration parameter (format: yyyymmdd) +specifies the release date of a stable release or snapshot release. + +If you upgrade from Postfix 3.6 or earlier, please read RELEASE_NOTES-3.7 +before proceeding. + +Dual license +------------ + +As of Postfix 3.2.5 this software is distributed with a dual license: +in addition to the historical IBM Public License (IPL) 1.0, it is +now also distributed with the more recent Eclipse Public License +(EPL) 2.0. Recipients can choose to take the software under the +license of their choice. Those who are more comfortable with the +IPL can continue with that license. + +Major changes - documentation and code cleanup +---------------------------------------------- + +There are numerous small fixes to Postfix documentation, and small +code-health changes that should not affect documented behavior but +may improve Postfix behavior for malformed input, or that make +Postfix easier to maintain. See the HISTORY file for details. + +Major changes - SRV support +--------------------------- + +[Feature 20230214] Support to look up DNS SRV records in the Postfix +SMTP/LMTP client, Based on code by Tomas Korbar (Red Hat). + +For example, with "use_srv_lookup = submission" and "relayhost = +example.com:submission", the Postfix SMTP client will look up DNS +SRV records for _submission._tcp.example.com, and will relay email +through the hosts and ports that are specified with those records. + +See https://www.postfix.org/postconf.5.html#use_srv_lookup for more +details, including how to selectively use SRV in a configuration +that connects to multiple ISP accounts. + +SRV support may also be useful inside a cloud-based infrastructure +when Postfix needs to deliver mail to services that run on a +dynamically-allocated port. + +Major changes - TLS support +--------------------------- + +[Incompat 20230304] This introduces the following changes: + +- Postfix treats the "export" and "low" cipher grade settings as + "medium". The "export" and "low" grades are no longer supported + in OpenSSL 1.1.1, the minimum version that Postfix requires. + +- Postfix default settings now exclude the following deprecated or + unused ciphers (SEED, IDEA, 3DES, RC2, RC4, RC5), digest (MD5), + key exchange algorithms (DH, ECDH), and public key algorithm + (DSS). + +[Feature 20230108] New configuration parameter tls_ffdhe_auto_groups +for finite-field Diffie-Hellman ephemeral (FFDHE) support in TLS +1.3 with OpenSSL 3.0. + +Major changes - attack resistance +--------------------------------- + +[Feature 20240312] the Postfix SMTP server can now aggregate +smtpd_client_*_rate and smtpd_client_*_count statistics by network +block, as specified with smtpd_client_ipv4_prefix_length (default +32, no aggregation) and smtpd_client_ipv6_prefix_length (default +84, aggregation by /84 network blocks). The latter raises the bar +for a memory exhaustion attack. + +[Feature 20221023] Unconditionally disable a CPU resource attack +requesting TLS renegotiation. There's no good reason to support +this in the middle of an SMTP connection. + +Major changes - bit rot +----------------------- + +[Incompat 20221228] Postfix documentation and code have been converted +to use "grep -E" and "grep -F" instead of the historical forms +"egrep" and "fgrep". To build Postfix on a system that supports +only the historical forms, run the script auxiliary/fix-grep/fix-grep.sh +to revert this change. + +Major changes - configuration checks +------------------------------------ + +[Feature 20240406] The postconf command now warns for #comment in +or after a Postfix parameter value. Postfix programs do not support +#comment after other text, and treat that as input. + +Major changes - database support +-------------------------------- + +[Incompat 20220509] The PostgreSQL client encoding is now configurable +with the "encoding" Postfix configuration file attribute. The default +is "UTF8". Previously the encoding was hard-coded as "LATIN1". + +Major changes - logging +----------------------- + +[Incompat 20230308] The postfix(1) and postlog(1) commands now +produce stderr logging even when stderr is not connected to a +terminal. This eliminates an inconsistency, and makes these programs +easier to use in some automated procedures. The canonical example +is to capture output from "postmulti -p status" to figure out which +instances are or are not running. + +Major changes - source code organization +---------------------------------------- + +[Incompat 20220507] Most global/mkmap*.[hc] files are moved to the +util directory; only global/mkmap_proxy.* remains. The old file +organization was designed before support for dynamically-loadable +databases was added, and that code suffered from complexity. + diff --git a/WISHLIST b/WISHLIST index bc52ebc..f3d9860 100644 --- a/WISHLIST +++ b/WISHLIST @@ -6,6 +6,25 @@ Wish list: Disable -DSNAPSHOT and -DNONPROD in makedefs. + The postconf command needs more mongodb tests. + + The mongodb client needs tests. + + Remove .printfck directories, and remove printfck targets + from Makefiles. + + In documentation and configuration file examples, replace + IPv4 address prefixes from Cloud9 with 192.168.* from RFC + 1918, and replace IPv6 address prefixes with unique local + IPv6 address prefixes fd00:* from RFC 4193. + + Add a pre-release check for '.' instead of ','. Generalize + from grep '[a-zA-Z0-9]\. *[a-z]' proto/*|egrep -v + 'i\.e\.|etc\.|e\.g\.|\. *[a-zA-Z0-9]*\(' + + Update DKIM examples for signing with the benefits of forced + MIME converison with "force_mime_input_conversion = yes" + Scan Postfix code with github.com/googleprojectzero/weggli (depends on "rust"). @@ -14,16 +33,16 @@ Wish list: Check out https://github.com/milter-manager/milter-manager/ - Check out https://cutter.osdn.jp/ (C/C++ unit tests). + Check out https://github.com/clear-code/cutter + (https://cutter.osdn.jp/) for C/C++ unit tests. - Follow https://github.com/vdukhovni/postfix/commits/rpk + postscreen hints to smtpd to suppress the server greeting + after a remote SMTP client has pregreeted. This makes the + PIPELINING detection more meaningful. Multi-recipient support in sender/recipient_bcc_maps and always_bcc. - Test for dns_rr_copy() + dns_rr_free(). - - mail_conf_xxx supprt for non-negative numbers (i.e. numbers with a lower bound of zero). diff --git a/conf/access b/conf/access index 97892eb..6da2db2 100644 --- a/conf/access +++ b/conf/access @@ -59,7 +59,7 @@ # line that starts with whitespace continues a logi- # cal line. # -# EMAIL ADDRESS PATTERNS +# EMAIL ADDRESS PATTERNS IN INDEXED TABLES # With lookups from indexed files such as DB or DBM, or from # networked tables such as NIS, LDAP or SQL, patterns are # tried in the order as listed below: @@ -97,7 +97,7 @@ # becomes: user+foo@domain, user@domain, domain, user+foo@, # and user@. # -# HOST NAME/ADDRESS PATTERNS +# HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES # With lookups from indexed files such as DB or DBM, or from # networked tables such as NIS, LDAP or SQL, the following # lookup patterns are examined in the order as listed: diff --git a/conf/aliases b/conf/aliases index 8f1a284..280c3d2 100644 --- a/conf/aliases +++ b/conf/aliases @@ -45,25 +45,29 @@ decode: root # newaliases # # DESCRIPTION -# The aliases(5) table provides a system-wide mechanism to -# redirect mail for local recipients. The redirections are -# processed by the Postfix local(8) delivery agent. +# The optional aliases(5) table (alias_maps) redirects mail +# for local recipients. The redirections are processed by +# the Postfix local(8) delivery agent. +# +# This is unlike virtual(5) aliasing (virtual_alias_maps) +# which applies to all recipients: local(8), virtual, and +# remote, and which is implemented by the cleanup(8) daemon. # # Normally, the aliases(5) table is specified as a text file -# that serves as input to the postalias(1) command. The -# result, an indexed file in dbm or db format, is used for -# fast lookup by the mail system. Execute the command -# newaliases in order to rebuild the indexed file after +# that serves as input to the postalias(1) command. The +# result, an indexed file in dbm or db format, is used for +# fast lookup by the mail system. Execute the command +# newaliases in order to rebuild the indexed file after # changing the Postfix alias database. # -# When the table is provided via other means such as NIS, -# LDAP or SQL, the same lookups are done as for ordinary +# When the table is provided via other means such as NIS, +# LDAP or SQL, the same lookups are done as for ordinary # indexed files. # -# Alternatively, the table can be provided as a regu- -# lar-expression map where patterns are given as regular -# expressions. In this case, the lookups are done in a -# slightly different way as described below under "REGULAR +# Alternatively, the table can be provided as a regu- +# lar-expression map where patterns are given as regular +# expressions. In this case, the lookups are done in a +# slightly different way as described below under "REGULAR # EXPRESSION TABLES". # # Users can control delivery of their own mail by setting up @@ -77,61 +81,61 @@ decode: root # # name: value1, value2, ... # -# o Empty lines and whitespace-only lines are ignored, -# as are lines whose first non-whitespace character +# o Empty lines and whitespace-only lines are ignored, +# as are lines whose first non-whitespace character # is a `#'. # -# o A logical line starts with non-whitespace text. A -# line that starts with whitespace continues a logi- +# o A logical line starts with non-whitespace text. A +# line that starts with whitespace continues a logi- # cal line. # -# The name is a local address (no domain part). Use double -# quotes when the name contains any special characters such -# as whitespace, `#', `:', or `@'. The name is folded to +# The name is a local address (no domain part). Use double +# quotes when the name contains any special characters such +# as whitespace, `#', `:', or `@'. The name is folded to # lowercase, in order to make database lookups case insensi- # tive. # -# In addition, when an alias exists for owner-name, this -# will override the envelope sender address, so that deliv- +# In addition, when an alias exists for owner-name, this +# will override the envelope sender address, so that deliv- # ery diagnostics are directed to owner-name, instead of the -# originator of the message (for details, see -# owner_request_special, expand_owner_alias and -# reset_owner_alias). This is typically used to direct -# delivery errors to the maintainer of a mailing list, who +# originator of the message (for details, see +# owner_request_special, expand_owner_alias and +# reset_owner_alias). This is typically used to direct +# delivery errors to the maintainer of a mailing list, who # is in a better position to deal with mailing list delivery # problems than the originator of the undelivered mail. # # The value contains one or more of the following: # # address -# Mail is forwarded to address, which is compatible +# Mail is forwarded to address, which is compatible # with the RFC 822 standard. # # /file/name -# Mail is appended to /file/name. For details on how -# a file is written see the sections "EXTERNAL FILE -# DELIVERY" and "DELIVERY RIGHTS" in the local(8) -# documentation. Delivery is not limited to regular -# files. For example, to dispose of unwanted mail, +# Mail is appended to /file/name. For details on how +# a file is written see the sections "EXTERNAL FILE +# DELIVERY" and "DELIVERY RIGHTS" in the local(8) +# documentation. Delivery is not limited to regular +# files. For example, to dispose of unwanted mail, # deflect it to /dev/null. # # |command -# Mail is piped into command. Commands that contain -# special characters, such as whitespace, should be -# enclosed between double quotes. For details on how -# a command is executed see "EXTERNAL COMMAND DELIV- +# Mail is piped into command. Commands that contain +# special characters, such as whitespace, should be +# enclosed between double quotes. For details on how +# a command is executed see "EXTERNAL COMMAND DELIV- # ERY" and "DELIVERY RIGHTS" in the local(8) documen- # tation. # # When the command fails, a limited amount of command -# output is mailed back to the sender. The file -# /usr/include/sysexits.h defines the expected exit -# status codes. For example, use "|exit 67" to simu- -# late a "user unknown" error, and "|exit 0" to +# output is mailed back to the sender. The file +# /usr/include/sysexits.h defines the expected exit +# status codes. For example, use "|exit 67" to simu- +# late a "user unknown" error, and "|exit 0" to # implement an expensive black hole. # # :include:/file/name -# Mail is sent to the destinations listed in the +# Mail is sent to the destinations listed in the # named file. Lines in :include: files have the same # syntax as the right-hand side of alias entries. # @@ -143,12 +147,12 @@ decode: root # # ADDRESS EXTENSION # When alias database search fails, and the recipient local- -# part contains the optional recipient delimiter (e.g., -# user+foo), the search is repeated for the unextended +# part contains the optional recipient delimiter (e.g., +# user+foo), the search is repeated for the unextended # address (e.g., user). # -# The propagate_unmatched_extensions parameter controls -# whether an unmatched address extension (+foo) is propa- +# The propagate_unmatched_extensions parameter controls +# whether an unmatched address extension (+foo) is propa- # gated to the result of table lookup. # # CASE FOLDING @@ -156,83 +160,85 @@ decode: root # to lowercase before database lookup. # # REGULAR EXPRESSION TABLES -# This section describes how the table lookups change when +# This section describes how the table lookups change when # the table is given in the form of regular expressions. For -# a description of regular expression lookup table syntax, -# see regexp_table(5) or pcre_table(5). NOTE: these formats +# a description of regular expression lookup table syntax, +# see regexp_table(5) or pcre_table(5). NOTE: these formats # do not use ":" at the end of a pattern. # -# Each regular expression is applied to the entire search -# string. Thus, a search string user+foo is not broken up +# Each regular expression is applied to the entire search +# string. Thus, a search string user+foo is not broken up # into user and foo. # -# Regular expressions are applied in the order as specified -# in the table, until a regular expression is found that +# Regular expressions are applied in the order as specified +# in the table, until a regular expression is found that # matches the search string. # -# Lookup results are the same as with indexed file lookups. -# For security reasons there is no support for $1, $2 etc. +# Lookup results are the same as with indexed file lookups. +# For security reasons there is no support for $1, $2 etc. # substring interpolation. # # SECURITY -# The local(8) delivery agent disallows regular expression -# substitution of $1 etc. in alias_maps, because that would +# The local(8) delivery agent disallows regular expression +# substitution of $1 etc. in alias_maps, because that would # open a security hole. # -# The local(8) delivery agent will silently ignore requests -# to use the proxymap(8) server within alias_maps. Instead -# it will open the table directly. Before Postfix version -# 2.2, the local(8) delivery agent will terminate with a +# The local(8) delivery agent will silently ignore requests +# to use the proxymap(8) server within alias_maps. Instead +# it will open the table directly. Before Postfix version +# 2.2, the local(8) delivery agent will terminate with a # fatal error. # # CONFIGURATION PARAMETERS -# The following main.cf parameters are especially relevant. -# The text below provides only a parameter summary. See +# The following main.cf parameters are especially relevant. +# The text below provides only a parameter summary. See # postconf(5) for more details including examples. # # alias_database (see 'postconf -d' output) -# The alias databases for local(8) delivery that are +# The alias databases for local(8) delivery that are # updated with "newaliases" or with "sendmail -bi". # # alias_maps (see 'postconf -d' output) -# The alias databases that are used for local(8) -# delivery. +# Optional lookup tables with aliases that apply only +# to local(8) recipients; this is unlike vir- +# tual_alias_maps that apply to all recipients: +# local(8), virtual, and remote. # # allow_mail_to_commands (alias, forward) -# Restrict local(8) mail delivery to external com- +# Restrict local(8) mail delivery to external com- # mands. # # allow_mail_to_files (alias, forward) -# Restrict local(8) mail delivery to external files. +# Restrict local(8) mail delivery to external files. # # expand_owner_alias (no) # When delivering to an alias "aliasname" that has an # "owner-aliasname" companion alias, set the envelope -# sender address to the expansion of the +# sender address to the expansion of the # "owner-aliasname" alias. # # propagate_unmatched_extensions (canonical, virtual) -# What address lookup tables copy an address exten- +# What address lookup tables copy an address exten- # sion from the lookup key to the lookup result. # # owner_request_special (yes) # Enable special treatment for owner-listname entries # in the aliases(5) file, and don't split owner-list- -# name and listname-request address localparts when +# name and listname-request address localparts when # the recipient_delimiter is set to "-". # # recipient_delimiter (empty) -# The set of characters that can separate an email -# address localpart, user name, or a .forward file +# The set of characters that can separate an email +# address localpart, user name, or a .forward file # name from its extension. # # Available in Postfix version 2.3 and later: # # frozen_delivered_to (yes) -# Update the local(8) delivery agent's idea of the -# Delivered-To: address (see prepend_deliv- -# ered_header) only once, at the start of a delivery -# attempt; do not update the Delivered-To: address +# Update the local(8) delivery agent's idea of the +# Delivered-To: address (see prepend_deliv- +# ered_header) only once, at the start of a delivery +# attempt; do not update the Delivered-To: address # while expanding aliases or .forward files. # # STANDARDS @@ -245,12 +251,12 @@ decode: root # postconf(5), configuration parameters # # README FILES -# Use "postconf readme_directory" or "postconf html_direc- +# Use "postconf readme_directory" or "postconf html_direc- # tory" to locate this information. # DATABASE_README, Postfix lookup table overview # # LICENSE -# The Secure Mailer license must be distributed with this +# The Secure Mailer license must be distributed with this # software. # # AUTHOR(S) diff --git a/conf/canonical b/conf/canonical index 4957fcc..894fd5b 100644 --- a/conf/canonical +++ b/conf/canonical @@ -225,57 +225,56 @@ # Other parameters of interest: # # inet_interfaces (all) -# The network interface addresses that this mail sys- -# tem receives mail on. +# The local network interface addresses that this +# mail system receives mail on. # # local_header_rewrite_clients (permit_inet_interfaces) -# Rewrite message header addresses in mail from these -# clients and update incomplete addresses with the -# domain name in $myorigin or $mydomain; either don't -# rewrite message headers from other clients at all, -# or rewrite message headers and update incomplete -# addresses with the domain specified in the -# remote_header_rewrite_domain parameter. +# Rewrite or add message headers in mail from these +# clients, updating incomplete addresses with the +# domain name in $myorigin or $mydomain, and adding +# missing headers. # # proxy_interfaces (empty) -# The network interface addresses that this mail sys- -# tem receives mail on by way of a proxy or network -# address translation unit. +# The remote network interface addresses that this +# mail system receives mail on by way of a proxy or +# network address translation unit. # -# masquerade_classes (envelope_sender, header_sender, +# masquerade_classes (envelope_sender, header_sender, # header_recipient) # What addresses are subject to address masquerading. # # masquerade_domains (empty) -# Optional list of domains whose subdomain structure +# Optional list of domains whose subdomain structure # will be stripped off in email addresses. # # masquerade_exceptions (empty) -# Optional list of user names that are not subjected -# to address masquerading, even when their addresses +# Optional list of user names that are not subjected +# to address masquerading, even when their addresses # match $masquerade_domains. # # mydestination ($myhostname, localhost.$mydomain, local- # host) -# The list of domains that are delivered via the +# The list of domains that are delivered via the # $local_transport mail delivery transport. # # myorigin ($myhostname) # The domain name that locally-posted mail appears to -# come from, and that locally posted mail is deliv- +# come from, and that locally posted mail is deliv- # ered to. # # owner_request_special (yes) # Enable special treatment for owner-listname entries # in the aliases(5) file, and don't split owner-list- -# name and listname-request address localparts when +# name and listname-request address localparts when # the recipient_delimiter is set to "-". # # remote_header_rewrite_domain (empty) -# Don't rewrite message headers from remote clients -# at all when this parameter is empty; otherwise, re- -# write message headers and append the specified -# domain name to incomplete addresses. +# Rewrite or add message headers in mail from remote +# clients if the remote_header_rewrite_domain parame- +# ter value is non-empty, updating incomplete +# addresses with the domain specified in the +# remote_header_rewrite_domain parameter, and adding +# missing headers. # # SEE ALSO # cleanup(8), canonicalize and enqueue mail @@ -284,13 +283,13 @@ # virtual(5), virtual aliasing # # README FILES -# Use "postconf readme_directory" or "postconf html_direc- +# Use "postconf readme_directory" or "postconf html_direc- # tory" to locate this information. # DATABASE_README, Postfix lookup table overview # ADDRESS_REWRITING_README, address rewriting guide # # LICENSE -# The Secure Mailer license must be distributed with this +# The Secure Mailer license must be distributed with this # software. # # AUTHOR(S) diff --git a/conf/dynamicmaps.cf b/conf/dynamicmaps.cf index 5179f66..feeb6a1 100644 --- a/conf/dynamicmaps.cf +++ b/conf/dynamicmaps.cf @@ -2,6 +2,7 @@ cdb ${LIB_PREFIX}cdb${LIB_SUFFIX} dict_cdb_open mkmap_cdb_open ldap ${LIB_PREFIX}ldap${LIB_SUFFIX} dict_ldap_open lmdb ${LIB_PREFIX}lmdb${LIB_SUFFIX} dict_lmdb_open mkmap_lmdb_open +mongodb ${LIB_PREFIX}mongodb${LIB_SUFFIX} dict_mongodb_open mysql ${LIB_PREFIX}mysql${LIB_SUFFIX} dict_mysql_open pcre ${LIB_PREFIX}pcre${LIB_SUFFIX} dict_pcre_open pgsql ${LIB_PREFIX}pgsql${LIB_SUFFIX} dict_pgsql_open diff --git a/conf/generic b/conf/generic index f371eb9..508e44a 100644 --- a/conf/generic +++ b/conf/generic @@ -193,13 +193,13 @@ # Other parameters of interest: # # inet_interfaces (all) -# The network interface addresses that this mail sys- -# tem receives mail on. +# The local network interface addresses that this +# mail system receives mail on. # # proxy_interfaces (empty) -# The network interface addresses that this mail sys- -# tem receives mail on by way of a proxy or network -# address translation unit. +# The remote network interface addresses that this +# mail system receives mail on by way of a proxy or +# network address translation unit. # # mydestination ($myhostname, localhost.$mydomain, local- # host) diff --git a/conf/header_checks b/conf/header_checks index bcd96a9..db295d0 100644 --- a/conf/header_checks +++ b/conf/header_checks @@ -440,46 +440,32 @@ # tent-Length:, Return-Path:. # # CONFIGURATION PARAMETERS -# body_checks -# Lookup tables with content filter rules for message -# body lines. These filters see one physical line at -# a time, in chunks of at most $line_length_limit -# bytes. -# -# body_checks_size_limit -# The amount of content per message body segment -# (attachment) that is subjected to $body_checks fil- -# tering. -# -# header_checks -# -# mime_header_checks (default: $header_checks) -# -# nested_header_checks (default: $header_checks) -# Lookup tables with content filter rules for message -# header lines: respectively, these are applied to -# the initial message headers (not including MIME -# headers), to the MIME headers anywhere in the mes- -# sage, and to the initial headers of attached mes- -# sages. -# -# Note: these filters see one logical message header -# at a time, even when a message header spans multi- -# ple lines. Message headers that are longer than -# $header_size_limit characters are truncated. -# -# disable_mime_input_processing -# While receiving mail, give no special treatment to -# MIME related message headers; all text after the -# initial message headers is considered to be part of -# the message body. This means that header_checks is -# applied to all the initial message headers, and -# that body_checks is applied to the remainder of the -# message. -# -# Note: when used in this manner, body_checks will -# process a multi-line message header one line at a -# time. +# body_checks (empty) +# Optional lookup tables for content inspection as +# specified in the body_checks(5) manual page. +# +# body_checks_size_limit (51200) +# How much text in a message body segment (or attach- +# ment, if you prefer to use that term) is subjected +# to body_checks inspection. +# +# header_checks (empty) +# Optional lookup tables for content inspection of +# primary non-MIME message headers, as specified in +# the header_checks(5) manual page. +# +# mime_header_checks ($header_checks) +# Optional lookup tables for content inspection of +# MIME related message headers, as described in the +# header_checks(5) manual page. +# +# nested_header_checks ($header_checks) +# Optional lookup tables for content inspection of +# non-MIME message headers in attached messages, as +# described in the header_checks(5) manual page. +# +# disable_mime_input_processing (no) +# Turn off MIME processing while receiving mail. # # EXAMPLES # Header pattern to block attachments with bad file name diff --git a/conf/main.cf b/conf/main.cf index 2ee7996..2f4eba9 100644 --- a/conf/main.cf +++ b/conf/main.cf @@ -31,7 +31,7 @@ # # The level below is what should be used with new (not upgrade) installs. # -compatibility_level = 3.8 +compatibility_level = 3.9 # SOFT BOUNCE # @@ -452,7 +452,7 @@ unknown_local_recipient_reject_code = 550 # The mailbox_command parameter specifies the optional external # command to use instead of mailbox delivery. The command is run as # the recipient with proper HOME, SHELL and LOGNAME environment settings. -# Exception: delivery for root is done as $default_user. +# Exception: delivery for root is done as $default_privs. # # Other environment variables of interest: USER (recipient username), # EXTENSION (address extension), DOMAIN (domain part of address), diff --git a/conf/post-install b/conf/post-install index 2a7d99b..ed7c79a 100644 --- a/conf/post-install +++ b/conf/post-install @@ -205,6 +205,10 @@ # Google, Inc. # 111 8th Avenue # New York, NY 10011, USA +# +# Wietse Venema +# porcupine.org +# Amawalk, NY 10501, USA #-- umask 022 @@ -291,7 +295,7 @@ test -d "$config_directory" || { # XXX Solaris does not have "test -e". instances=`test ! -f $def_config_directory/main.cf || - $POSTCONF -c $def_config_directory -h multi_instance_directories | + $POSTCONF -qc $def_config_directory -h multi_instance_directories | sed 's/,/ /'` || exit 1 update_shared_files=1 @@ -360,7 +364,7 @@ test -f $config_directory/main.cf && { case "$junk" in "") eval unset $name;; esac - eval : \${$name=\`$POSTCONF -c $config_directory -h $name\`} || exit 1 + eval : \${$name=\`$POSTCONF -qc $config_directory -h $name\`} || exit 1 done } @@ -461,14 +465,14 @@ override= for name in $MOST_PARAMETERS do eval junk=\"\$$name\" - test "$junk" = "`$POSTCONF -c $config_directory -h $name`" || { + test "$junk" = "`$POSTCONF -qc $config_directory -h $name`" || { override=1 break } done test -n "$override" && { - $POSTCONF -c $config_directory -e \ + $POSTCONF -qc $config_directory -e \ "daemon_directory = $daemon_directory" \ "command_directory = $command_directory" \ "queue_directory = $queue_directory" \ @@ -679,13 +683,13 @@ EOF # require now is that defer and deferred are hashed because those # can contain lots of files. - found=`$POSTCONF -c $config_directory -h hash_queue_names` + found=`$POSTCONF -qc $config_directory -h hash_queue_names` missing= (echo "$found" | grep defer >/dev/null) || missing="$missing defer" (echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred" test -n "$missing" && { echo fixing main.cf hash_queue_names for missing $missing - $POSTCONF -c $config_directory -e hash_queue_names="$found$missing" || + $POSTCONF -qc $config_directory -e hash_queue_names="$found$missing" || exit 1 } @@ -857,14 +861,14 @@ EOF # when IPv6 support is not compiled in. See util/sys_defs.h. test "`$POSTCONF -dh inet_protocols`" = "ipv4" || - test -n "`$POSTCONF -c $config_directory -n inet_protocols`" || { + test -n "`$POSTCONF -qc $config_directory -n inet_protocols`" || { cat </dev/null + $daemon_directory/master -t 2>/dev/null && { $FATAL the Postfix mail system is not running exit 1 @@ -244,6 +251,9 @@ check) status) + # Warn once for deprecated parameters. + $command_directory/postconf >/dev/null + $daemon_directory/master -t 2>/dev/null && { $INFO the Postfix mail system is not running exit 1 @@ -268,12 +278,12 @@ check-fatal) exit 1 } - maillog_file=`$command_directory/postconf -h maillog_file` || { + maillog_file=`$command_directory/postconf -qh maillog_file` || { $FATAL cannot execute $command_directory/postconf! exit 1 } test -n "$maillog_file" && { - $command_directory/postconf -M postlog/unix-dgram 2>/dev/null \ + $command_directory/postconf -qM postlog/unix-dgram 2>/dev/null \ | grep . >/dev/null || { $FATAL "missing 'postlog' service in master.cf - run 'postfix upgrade-configuration'" exit 1 @@ -291,6 +301,9 @@ check-fatal) check-warn) # This command is NOT part of the public interface. + # Warn once for deprecated parameters. + $command_directory/postconf >/dev/null + # Check Postfix root-owned directory owner/permissions. find $queue_directory/. $queue_directory/pid \ @@ -413,7 +426,7 @@ logrotate) for name in maillog_file maillog_file_compressor \ maillog_file_rotate_suffix do - value="`$command_directory/postconf -h $name`" + value="`$command_directory/postconf -qh $name`" case "$value" in "") $FATAL "empty '$name' parameter value - logfile rotation failed" exit 1;; diff --git a/conf/relocated b/conf/relocated index 90f63ec..5c43266 100644 --- a/conf/relocated +++ b/conf/relocated @@ -131,8 +131,8 @@ # Other parameters of interest: # # inet_interfaces (all) -# The network interface addresses that this mail sys- -# tem receives mail on. +# The local network interface addresses that this +# mail system receives mail on. # # mydestination ($myhostname, localhost.$mydomain, local- # host) @@ -145,9 +145,9 @@ # ered to. # # proxy_interfaces (empty) -# The network interface addresses that this mail sys- -# tem receives mail on by way of a proxy or network -# address translation unit. +# The remote network interface addresses that this +# mail system receives mail on by way of a proxy or +# network address translation unit. # # SEE ALSO # trivial-rewrite(8), address resolver diff --git a/conf/virtual b/conf/virtual index e99eee4..8200ca4 100644 --- a/conf/virtual +++ b/conf/virtual @@ -11,98 +11,99 @@ # postmap -q - /etc/postfix/virtual
  • The list of domains that are a member of that address -class: for example, all local domains, or all relay domains.

    +class.

    + +

    Examples: all local domains, or all relay domains.

    + +
  • The default delivery transport for domains in that address +class.

    + +

    Examples: local_transport or relay_transport (these point +to services defined in master.cf).

    -
  • The default delivery transport for that address class. For -example, the local, -virtual or relay delivery transport (delivery transports are defined -in master.cf). This helps to keep Postfix configurations simple, -by avoiding the need for explicit routing information in transport -maps.

    +

    Benefit: this avoids the need for explicit routing information +in transport maps.

  • The list of valid recipient addresses for that address -class. The Postfix SMTP server rejects invalid recipients with -"User unknown in <name of address class here> table". This -helps to keep the Postfix queue free of undeliverable MAILER-DAEMON -messages.

    +class.

    + +

    Benefit: the Postfix SMTP server rejects an invalid recipient +with "User unknown in <name of address class> table", and +avoids sending a MAILER-DAEMON message with backscatter spam.

@@ -92,12 +97,12 @@ This domain class also includes mail for user@[ipaddress] when the IP address is listed with the inet_interfaces or proxy_interfaces parameters.

-
  • Valid recipient addresses are listed with the local_recipient_maps -parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP -server rejects invalid recipients with "User unknown in local -recipient table". If the local_recipient_maps parameter value is -empty, then the Postfix SMTP server accepts any address in the -local domain class.

    +
  • Valid recipient addresses for those domains are +listed with the local_recipient_maps parameter, as described in +LOCAL_RECIPIENT_README. The Postfix SMTP server rejects invalid recipients +with "User unknown in local recipient table". If the local_recipient_maps +parameter value is empty, then the Postfix SMTP server accepts any +address in the local domain class.

  • The mail delivery transport is specified with the local_transport parameter. The default value is local:$myhostname @@ -111,21 +116,25 @@ class.

    • Purpose: hosted domains where each recipient address is -aliased to an address in a different domain, for example, a local -UNIX system account or a remote address. A +aliased to an address in a different domain class, for example, a +local UNIX system account or a remote address. A virtual alias example is given in the VIRTUAL_README file.

    • Domain names are listed in virtual_alias_domains. The default value is $virtual_alias_maps for Postfix 1.1 compatibility.

      -
    • Valid recipient addresses are listed with the virtual_alias_maps -parameter. The Postfix SMTP server rejects invalid recipients with -"User unknown in virtual alias table". The default value is -$virtual_maps for Postfix 1.1 compatibility.

      +
    • Valid recipient addresses for those domains are listed with the +virtual_alias_maps parameter. The Postfix SMTP server rejects invalid +recipients with "User unknown in virtual alias table". The default +value is $virtual_maps for Postfix 1.1 compatibility.

      -
    • There is no mail delivery transport parameter. Every -address must be aliased to an address in some other domain.

      +

      Note: for historical reasons, virtual_alias_maps +apply to recipients in all domain classes, not only the virtual +alias domain class.

      + +
    • There is no configurable mail delivery transport. Every +address must be aliased to an address in some other domain class.

    @@ -136,18 +145,19 @@ class.

  • Purpose: final delivery for hosted domains where each recipient address can have its own mailbox, and where users do not -need to have a UNIX system account. A virtual mailbox example is +need to have a UNIX system account. A virtual mailbox example is given in the VIRTUAL_README file.

  • Domain names are listed with the virtual_mailbox_domains parameter. The default value is $virtual_mailbox_maps for Postfix 1.1 compatibility.

    -
  • Valid recipient addresses are listed with the virtual_mailbox_maps -parameter. The Postfix SMTP server rejects invalid recipients with -"User unknown in virtual mailbox table". If this parameter value -is empty, the Postfix SMTP server accepts all recipients for domains -listed in $virtual_mailbox_domains.

    +
  • Valid recipient addresses for those domains are listed +with the virtual_mailbox_maps parameter. The Postfix SMTP server +rejects invalid recipients with "User unknown in virtual mailbox +table". If this parameter value is empty, the Postfix SMTP server +accepts all recipients for domains listed in $virtual_mailbox_domains. +

  • The mail delivery transport is specified with the virtual_transport parameter. The default value is virtual @@ -169,11 +179,12 @@ file.

  • Domain names are listed with the relay_domains parameter.

    -
  • Valid recipient addresses are listed with the relay_recipient_maps -parameter. The Postfix SMTP server rejects invalid recipients with -"User unknown in relay recipient table". If this parameter value -is empty, the Postfix SMTP server accepts all recipients for domains -listed with the relay_domains parameter.

    +
  • Valid recipient addresses for those domains are listed +with the relay_recipient_maps parameter. The Postfix SMTP server +rejects invalid recipients with "User unknown in relay recipient +table". If this parameter value is empty, the Postfix SMTP server +accepts all recipients for domains listed with the relay_domains +parameter.

  • The mail delivery transport is specified with the relay_transport parameter. The default value is relay which diff --git a/html/ADDRESS_REWRITING_README.html b/html/ADDRESS_REWRITING_README.html index 85e296f..c92a314 100644 --- a/html/ADDRESS_REWRITING_README.html +++ b/html/ADDRESS_REWRITING_README.html @@ -94,9 +94,7 @@ as invalid

      -
    • Resolve address to destination - -
    • Mail transport switch +
    • Resolve address to (transport, next-hop destination)
    • Relocated users table @@ -312,8 +310,8 @@ find what you need.

      - + @@ -340,13 +338,12 @@ nowrap> all mail - - - - - + + + diff --git a/html/LOCAL_RECIPIENT_README.html b/html/LOCAL_RECIPIENT_README.html index a3a3636..5a614e0 100644 --- a/html/LOCAL_RECIPIENT_README.html +++ b/html/LOCAL_RECIPIENT_README.html @@ -57,7 +57,8 @@ all names or addresses of local recipients. A recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local username or address is not listed in $local_recipient_maps, then the Postfix SMTP server will reject -the address with "User unknown in local recipient table".

      +the address with "User unknown in local recipient table". Other +Postfix interfaces may still accept an "unknown" recipient.

      The default setting, shown below, assumes that you use the default Postfix local(8) delivery agent for local delivery, where diff --git a/html/MAILLOG_README.html b/html/MAILLOG_README.html index be58e33..ab751f4 100644 --- a/html/MAILLOG_README.html +++ b/html/MAILLOG_README.html @@ -63,10 +63,16 @@ Postfix version.

      /var/log/postfix.log. See also the "Logfile rotation" section below for logfile management.

      +

      In the example below, specifying maillog_file_permissions is +optional (Postfix 3.9 and later). The default value is 0600, i.e., +only the super-user can access the file; the value 0644 also +adds 'group' and 'other' read access.

      +
       # postfix stop
       # postconf maillog_file=/var/log/postfix.log
      +# postconf maillog_file_permissions=0644 # (Postfix 3.9 and later)
       # postfix start
       
      @@ -124,6 +130,10 @@ old logfile.

      program is configured with the maillog_file_compressor parameter (default: gzip).

      +
    • The next time it logs an event, postlogd(8) will create a +new logfile, with permissions specified with the maillog_file_permissions +parameter (default: 0600).

      +

      Notes:

      diff --git a/html/MILTER_README.html b/html/MILTER_README.html index c69a5bf..b72fdb8 100644 --- a/html/MILTER_README.html +++ b/html/MILTER_README.html @@ -630,7 +630,7 @@ and protocol.

      clients

      The smtpd_milter_maps feature supports different Milter settings -for different client IP addresses. Lookup results override the the +for different client IP addresses. Lookup results override the global smtpd_milters setting, and have the same syntax. For example, to disable Milter settings for local address ranges:

      diff --git a/html/MONGODB_README.html b/html/MONGODB_README.html new file mode 100644 index 0000000..a05d1f5 --- /dev/null +++ b/html/MONGODB_README.html @@ -0,0 +1,263 @@ + + + +Postfix MongoDB Howto + + + +

      Postfix MongoDB Howto

      +
      + +

      MongoDB Support in Postfix

      + +

      Postfix can use MongoDB as a source for any of its lookups: +aliases(5), virtual(5), canonical(5), etc. This allows you to keep +information for your mail service in a replicated noSQL database +with fine-grained access controls. By not storing it locally on the +mail server, the administrators can maintain it from anywhere, and +the users can control whatever bits of it you think appropriate. +You can have multiple mail servers using the same information, +without the hassle and delay of having to copy it to each.

      + +

      Topics covered in this document:

      + + + +

      Building Postfix with MongoDB support

      + +

      These instructions assume that you build Postfix from source +code as described in the INSTALL document. Some modification may +be required if you build Postfix from a vendor-specific source +package.

      + +

      The Postfix MongoDB client requires the mongo-c-driver +library. This can be built from source code from the +mongod-c project, or this can be installed as a binary package +from your OS distribution, typically named mongo-c-driver, +mongo-c-driver-devel or libmongoc-dev. +Installing the mongo-c-driver library may also install libbson +as a dependency.

      + +

      To build Postfix with mongodb map support, add to the CCARGS +environment variable the options -DHAS_MONGODB and -I for the +directory containing the mongodb headers, and specify the AUXLIBS_MONGODB +with the libmongoc and libbson libraries, for example:

      + +
      +
      +% make tidy
      +% make -f Makefile.init makefiles \
      +    CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
      +    -I/usr/include/libbson-1.0" \
      +    AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0"
      +
      +
      + +

      The 'make tidy' command is needed only if you have previously +built Postfix without MongoDB support.

      + +

      If your MongoDB shared library is in a directory that the RUN-TIME +linker does not know about, add a "-Wl,-R,/path/to/directory" option +after "-lbson-1.0". Then, just run 'make'.

      + +

      Configuring MongoDB lookups

      + +

      In order to use MongoDB lookups, define a MongoDB source as a +table lookup in main.cf, for example:

      + +
      +
      +alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf
      +
      +
      + +

      The file /etc/postfix/mongo-aliases.cf can specify a number of +parameters. For a complete description, see the mongodb_table(5) +manual page.

      + +

      Example: virtual(5) alias maps

      + +

      Here's a basic example for using MongoDB to look up virtual(5) +aliases. Assume that in main.cf, you have:

      + +
      +
      +virtual_alias_maps = hash:/etc/postfix/virtual_aliases, 
      +    proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf
      +
      +
      + +

      and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have:

      + +
      +
      +uri = mongodb+srv://user_name:password@some_server
      +dbname = mail
      +collection = mailbox
      +query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
      +result_attribute = username
      +
      +
      + +

      This example assumes mailbox names are stored in a MongoDB backend, +in a format like:

      + +
      +
      +{ "username": "user@example.com",
      +  "alias": [
      +    {"address": "admin@example.com"},
      +    {"address": "abuse@example.com"}
      +  ],
      +  "active": 1
      +}
      +
      +
      + +

      Upon receiving mail for "admin@example.com" that isn't found in the +/etc/postfix/virtual_aliases database, Postfix will search the +MongoDB server/cluster listening at port 27017 on some_server. It +will connect using the provided credentials, and search for any +entries whose username is, or alias field has "admin@example.com". +It will return the username attribute of those found, and build a +list of their email addresses.

      + +

      Notes:

      + +
        + +
      • As with projection (see below), the Postfix mongodb +client automatically removes the top-level '_id' field from a +result_attribute result.

      • + +
      • The Postfix mongodb client will only parse result fields +with data types UTF8, INT32, INT64 and ARRAY. Other fields will be +ignored, with a warning in the logs.

      • + +
      + +

      Example: Mailing lists

      + +

      When it comes to mailing lists, one way of implementing one would +be as below:

      + +
      +
      +{ "name": "dev@example.com", "active": 1, "address": 
      +  [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
      +
      +
      + +

      using the filter below, will result in a comma separated string +with all email addresses in this list.

      + +
      +
      +query_filter = {"name": "%s", "active": 1}
      +result_attribute = address
      +
      +
      + +

      Notes:

      + +
        + +
      • As with projection (see below), the Postfix mongodb +client automatically removes the top-level '_id' field from a +result_attribute result.

      • + +
      • The Postfix mongodb client will only parse result fields +with data types UTF8, INT32, INT64 and ARRAY. Other fields will be +ignored, with a warning in the logs.

      • + +
      + +

      Example: advanced projections

      + +

      This module also supports the use of more complex MongoDB +projections. There may be some use cases where operations such as +concatenation are necessary to be performed on the data retrieved +from the database. Although it is encouraged to keep the database +design simple enough so this is not necessary, postfix supports the +use of MongoDB projections to achieve the goal.

      + +

      Consider the example below:

      + +
      +
      +{ "username": "user@example.com",
      +  "local_part": "user",
      +  "domain": "example.com",
      +  "alias": [
      +    {"address": "admin@example.com"},
      +    {"address": "abuse@example.com"}
      +  ],
      +  "active": 1
      +}
      +
      +
      + +

      virtual_mailbox_maps can be created using below parameters in a +mongodb:/etc/postfix/mongo-virtual-mailboxes.cf file:

      + +
      +
      +uri = mongodb+srv://user_name:password@some_server
      +dbname = mail
      +collection = mailbox
      +query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
      +projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
      +
      +
      + +

      This will return 'example.com/user' path built from the database fields.

      + +

      A couple of considerations when using projections:

      + +
        + +
      • As with result_attribute, the Postfix mongodb client +automatically removes the top-level '_id' field from a projection +result.

      • + +
      • The Postfix mongodb client will only parse fields with data +types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, +with a warning in the logs. It is suggested to exclude any unnecessary +fields when using a projection.

      • + +
      + +

      Feedback

      + +

      If you have questions, send them to postfix-users@postfix.org. +Please include relevant information about your Postfix setup: +MongoDB-related output from postconf, which libraries you built +with, and such. If your question involves your database contents, +please include the applicable bits of some database entries.

      + +

      Credits

      + +
        + +
      • Stephan Ferraro (Aionda GmbH) implemented an early version of the +Postfix MongoDB client. + +
      • Hamid Maadani (Dextrous Technologies, LLC) added support for +projections and %letter interpolation, and added documentation. + +
      • Wietse Venema adopted and restructured the code and documentation. + +
      + + + + diff --git a/html/Makefile.in b/html/Makefile.in index c5481f8..7f23ed7 100644 --- a/html/Makefile.in +++ b/html/Makefile.in @@ -20,7 +20,7 @@ CONFIG = access.5.html aliases.5.html canonical.5.html relocated.5.html \ transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html \ cidr_table.5.html tcp_table.5.html header_checks.5.html \ ldap_table.5.html lmdb_table.5.html mysql_table.5.html \ - pgsql_table.5.html memcache_table.5.html \ + pgsql_table.5.html memcache_table.5.html mongodb_table.5.html \ master.5.html nisplus_table.5.html generic.5.html bounce.5.html \ postfix-wrapper.5.html sqlite_table.5.html socketmap_table.5.html OTHER = postfix-manuals.html @@ -298,6 +298,10 @@ memcache_table.5.html: ../proto/memcache_table PATH=../mantools:$$PATH; \ srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@ +mongodb_table.5.html: ../proto/mongodb_table + PATH=../mantools:$$PATH; \ + srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@ + mysql_table.5.html: ../proto/mysql_table PATH=../mantools:$$PATH; \ srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@ diff --git a/html/POSTSCREEN_README.html b/html/POSTSCREEN_README.html index bca2ef0..9bef8db 100644 --- a/html/POSTSCREEN_README.html +++ b/html/POSTSCREEN_README.html @@ -120,7 +120,7 @@ of time to deliver spam before their IP address becomes denylisted. To speed up spam deliveries, zombies make compromises in their SMTP protocol implementation. For example, they speak before their turn, or they ignore responses from SMTP servers and continue sending -mail even when the server tells them to go away.

      +commands even when the server tells them to go away.

      postscreen(8) uses a variety of measurements to recognize zombies. First, postscreen(8) determines if the remote SMTP client @@ -159,7 +159,7 @@ overhead for legitimate clients.

      Quick tests before everything else

      -

      Before engaging in SMTP-level tests. postscreen(8) queries a +

      Before engaging in SMTP-level tests, postscreen(8) queries a number of local deny and allowlists. These tests speed up the handling of known clients.

      diff --git a/html/TLS_README.html b/html/TLS_README.html index eb9965a..a77f69d 100644 --- a/html/TLS_README.html +++ b/html/TLS_README.html @@ -2266,82 +2266,124 @@ describe the corresponding table syntax:

      additional attributes are supported at this level.
      may
      Opportunistic TLS. -The optional "ciphers", "exclude" and "protocols" attributes -(available for opportunistic TLS with Postfix ≥ 2.6) override the -"smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols" -configuration parameters. At this level and higher, the optional -"servername" attribute (available with Postfix ≥ 3.4) overrides the -global "smtp_tls_servername" parameter, enabling per-destination -configuration of the SNI extension sent to the remote SMTP server.
      +The optional "ciphers", "exclude", and "protocols" attributes (available +for opportunistic TLS with Postfix ≥ 2.6) and "connection_reuse" +attribute (Postfix ≥ 3.4) override the "smtp_tls_ciphers", +"smtp_tls_exclude_ciphers", "smtp_tls_protocols", and +"smtp_tls_connection_reuse" configuration parameters. At this level and +higher, the optional "servername" attribute (available with Postfix ≥ +3.4) overrides the global "smtp_tls_servername" parameter, enabling +per-destination configuration of the SNI extension sent to the remote +SMTP server. The optional "enable_rpk" attribute (Postfix ≥ 3.9) +overrides the main.cf smtp_tls_enable_rpk parameter. When opportunistic +TLS handshakes fail, Postfix retries the connection with TLS disabled. +This allows mail delivery to sites with non-interoperable TLS +implementations.
      encrypt
      Mandatory encryption. -Mail is delivered only if the remote SMTP server offers STARTTLS -and the TLS handshake succeeds. At this level and higher, the optional +Mail is delivered only if the remote SMTP server offers STARTTLS and the +TLS handshake succeeds. At this level and higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols -parameter, the optional "ciphers" attribute overrides the -main.cf smtp_tls_mandatory_ciphers parameter, and the optional -"exclude" attribute (Postfix ≥ 2.6) overrides the main.cf -smtp_tls_mandatory_exclude_ciphers parameter.
      +parameter, the optional "ciphers" attribute overrides the main.cf +smtp_tls_mandatory_ciphers parameter, the optional "exclude" attribute +(Postfix ≥ 2.6) overrides the main.cf +smtp_tls_mandatory_exclude_ciphers parameter, and the optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute +(Postfix ≥ 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. +
      dane
      Opportunistic DANE TLS. The TLS policy for the destination is obtained via TLSA records in -DNSSEC. If no TLSA records are found, the effective security level -used is may. If TLSA records are -found, but none are usable, the effective security level is encrypt. When usable TLSA records -are obtained for the remote SMTP server, SSLv2+3 are automatically -disabled (see smtp_tls_mandatory_protocols), and the server certificate -must match the TLSA records. RFC 7672 (DANE) TLS authentication -and DNSSEC support is available with Postfix 2.11 and later.
      +DNSSEC. If no TLSA records are found, the effective security level used +is may. If TLSA records are found, but +none are usable, the effective security level is encrypt. When usable TLSA records are +obtained for the remote SMTP server, the server certificate must match +the TLSA records (and the SNI name is unconditionally set to the TLSA +base domain). RFC 7672 (DANE) TLS authentication and DNSSEC +support is available with Postfix 2.11 and later. The optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. When the effective security level +used is may, the optional "ciphers", +"exclude", and "protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_ciphers", "smtp_tls_exclude_ciphers", and "smtp_tls_protocols" +configuration parameters. When the effective security level used is encrypt, the optional "ciphers", +"exclude", and "protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and +"smtp_tls_mandatory_protocols" configuration parameters.
      dane-only
      Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA records in -DNSSEC. If no TLSA records are found, or none are usable, no -connection is made to the server. When usable TLSA records are -obtained for the remote SMTP server, SSLv2+3 are automatically disabled -(see smtp_tls_mandatory_protocols), and the server certificate must -match the TLSA records. RFC 7672 (DANE) TLS authentication and -DNSSEC support is available with Postfix 2.11 and later.
      +DNSSEC. If no TLSA records are found, or none are usable, no connection +is made to the server. When usable TLSA records are obtained for the +remote SMTP server, the server certificate must match the TLSA records. +RFC 7672 (DANE) TLS authentication and DNSSEC support is available with +Postfix 2.11 and later. The optional "ciphers", "exclude", and +"protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and +"smtp_tls_mandatory_protocols" configuration parameters. The optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter.
      fingerprint
      Certificate -fingerprint verification. Available with Postfix 2.5 and -later. At this security level, there are no trusted Certification -Authorities. The certificate trust chain, expiration date, ... are -not checked. Instead, the optional match attribute, or else -the main.cf smtp_tls_fingerprint_cert_match parameter, lists -the server certificate fingerprints or public key fingerprints -(Postfix 2.9 and later). The -digest algorithm used to calculate fingerprints is selected by the -smtp_tls_fingerprint_digest parameter. Multiple fingerprints can -be combined with a "|" delimiter in a single match attribute, or multiple -match attributes can be employed. The ":" character is not used as a -delimiter as it occurs between each pair of fingerprint (hexadecimal) -digits.
      +fingerprint verification. Available with Postfix 2.5 and later. At +this security level, there are no trusted Certification Authorities. The +certificate trust chain, expiration date, ... are not checked. Instead, +the optional "match" attribute, or else the main.cf +smtp_tls_fingerprint_cert_match parameter, lists the certificate +fingerprints or the public key fingerprints (Postfix 2.9 and later) of +acceptable server certificates. The digest algorithm used to calculate +the fingerprint is selected by the smtp_tls_fingerprint_digest +parameter. Multiple fingerprints can be combined with a "|" delimiter in +a single match attribute, or multiple match attributes can be employed. +The ":" character is not used as a delimiter as it occurs between each +pair of fingerprint (hexadecimal) digits. The optional "ciphers", +"exclude", and "protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and +"smtp_tls_mandatory_protocols" configuration parameters. The optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. The optional "enable_rpk" +attribute (Postfix ≥ 3.9) overrides the main.cf smtp_tls_enable_rpk +parameter.
      verify
      Mandatory -server certificate verification. Mail is delivered only if the -TLS handshake succeeds, if the remote SMTP server certificate can -be validated (not expired or revoked, and signed by a trusted -Certification Authority), and if the server certificate name matches -the optional "match" attribute (or the main.cf smtp_tls_verify_cert_match -parameter value when no optional "match" attribute is specified). -With Postfix ≥ 2.11 the "tafile" attribute optionally modifies -trust chain verification in the same manner as the -"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute -may be specified multiple times to load multiple trust-anchor -files.
      +server certificate verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups are presumed to be +secure enough, and the name verified in the server certificate is +potentially obtained via unauthenticated DNS MX lookups. The server +certificate name must match either the optional "match" attribute, or +else the main.cf smtp_tls_verify_cert_match parameter value. With +Postfix ≥ 2.11 the "tafile" attribute optionally modifies trust chain +verification in the same manner as the "smtp_tls_trust_anchor_file" +parameter. The "tafile" attribute may be specified multiple times to +load multiple trust-anchor files. The optional "connection_reuse" +attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter.
      secure
      Secure certificate -verification. Mail is delivered only if the TLS handshake succeeds, -and DNS forgery resistant remote SMTP certificate verification succeeds -(not expired or revoked, and signed by a trusted Certification Authority), -and if the server certificate name matches the optional "match" attribute -(or the main.cf smtp_tls_secure_cert_match parameter value when no optional -"match" attribute is specified). With Postfix ≥ 2.11 the "tafile" -attribute optionally modifies trust chain verification in the same manner -as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute -may be specified multiple times to load multiple trust-anchor -files.
      +verification. +Mail is delivered only if the TLS handshake succeeds, the remote SMTP +server certificate chain can be validated, and a DNS name in the +certificate matches the specified match criteria. At this security +level, DNS MX lookups, though potentially used to determine the +candidate next-hop gateway IP addresses, are not presumed to be +secure enough for TLS peername verification. Instead, the default name +verified in the server certificate is obtained directly from the +next-hop, or is explicitly specified via the optional "match" attribute +which overrides the main.cf smtp_tls_secure_cert_match parameter. The +optional "ciphers", "exclude", and "protocols" attributes (Postfix ≥ +2.6) override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix ≥ 2.11 the "tafile" attribute +optionally modifies trust chain verification in the same manner as the +"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be +specified multiple times to load multiple trust-anchor files. The +optional "connection_reuse" attribute (Postfix ≥ 3.4) overrides the +main.cf smtp_tls_connection_reuse parameter. diff --git a/html/access.5.html b/html/access.5.html index 24f844b..427eacf 100644 --- a/html/access.5.html +++ b/html/access.5.html @@ -60,7 +60,7 @@ ACCESS(5) ACCESS(5) A logical line starts with non-whitespace text. A line that starts with whitespace continues a logical line. -EMAIL ADDRESS PATTERNS +EMAIL ADDRESS PATTERNS IN INDEXED TABLES With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, patterns are tried in the order as listed below: @@ -92,7 +92,7 @@ ACCESS(5) ACCESS(5) (e.g., user+foo@domain), the lookup order becomes: user+foo@domain, user@domain, domain, user+foo@, and user@. -HOST NAME/ADDRESS PATTERNS +HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, the following lookup patterns are examined in the order as listed: diff --git a/html/aliases.5.html b/html/aliases.5.html index 27cfe69..79d01b4 100644 --- a/html/aliases.5.html +++ b/html/aliases.5.html @@ -14,9 +14,13 @@ ALIASES(5) ALIASES(5) newaliases DESCRIPTION - The aliases(5) table provides a system-wide mechanism to redirect mail - for local recipients. The redirections are processed by the Postfix - local(8) delivery agent. + The optional aliases(5) table (alias_maps) redirects mail for local + recipients. The redirections are processed by the Postfix local(8) + delivery agent. + + This is unlike virtual(5) aliasing (virtual_alias_maps) which applies + to all recipients: local(8), virtual, and remote, and which is imple- + mented by the cleanup(8) daemon. Normally, the aliases(5) table is specified as a text file that serves as input to the postalias(1) command. The result, an indexed file in @@ -144,7 +148,9 @@ ALIASES(5) ALIASES(5) "newaliases" or with "sendmail -bi". alias_maps (see 'postconf -d' output) - The alias databases that are used for local(8) delivery. + Optional lookup tables with aliases that apply only to local(8) + recipients; this is unlike virtual_alias_maps that apply to all + recipients: local(8), virtual, and remote. allow_mail_to_commands (alias, forward) Restrict local(8) mail delivery to external commands. diff --git a/html/canonical.5.html b/html/canonical.5.html index 68b6532..d051297 100644 --- a/html/canonical.5.html +++ b/html/canonical.5.html @@ -56,7 +56,7 @@ CANONICAL(5) CANONICAL(5) systems. The canonical(5) mapping is not to be confused with virtual alias sup- - port or with local aliasing. To change the destination but not the + port or with local aliasing. To change the destination but not the headers, use the virtual(5) or aliases(5) map instead. CASE FOLDING @@ -211,20 +211,18 @@ CANONICAL(5) CANONICAL(5) Other parameters of interest: inet_interfaces (all) - The network interface addresses that this mail system receives - mail on. + The local network interface addresses that this mail system + receives mail on. local_header_rewrite_clients (permit_inet_interfaces) - Rewrite message header addresses in mail from these clients and - update incomplete addresses with the domain name in $myorigin or - $mydomain; either don't rewrite message headers from other - clients at all, or rewrite message headers and update incomplete - addresses with the domain specified in the remote_header_re- - write_domain parameter. + Rewrite or add message headers in mail from these clients, + updating incomplete addresses with the domain name in $myorigin + or $mydomain, and adding missing headers. proxy_interfaces (empty) - The network interface addresses that this mail system receives - mail on by way of a proxy or network address translation unit. + The remote network interface addresses that this mail system + receives mail on by way of a proxy or network address transla- + tion unit. masquerade_classes (envelope_sender, header_sender, header_recipient) What addresses are subject to address masquerading. @@ -253,15 +251,17 @@ CANONICAL(5) CANONICAL(5) set to "-". remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and - append the specified domain name to incomplete addresses. + Rewrite or add message headers in mail from remote clients if + the remote_header_rewrite_domain parameter value is non-empty, + updating incomplete addresses with the domain specified in the + remote_header_rewrite_domain parameter, and adding missing head- + ers. SEE ALSO cleanup(8), canonicalize and enqueue mail postmap(1), Postfix lookup table manager postconf(5), configuration parameters - virtual(5), virtual aliasing + virtual(5), virtual aliasing README FILES DATABASE_README, Postfix lookup table overview diff --git a/html/cleanup.8.html b/html/cleanup.8.html index 6e662f6..e4ecd43 100644 --- a/html/cleanup.8.html +++ b/html/cleanup.8.html @@ -172,26 +172,26 @@ CLEANUP(8) CLEANUP(8) BEFORE QUEUE MILTER CONTROLS As of version 2.3, Postfix supports the Sendmail version 8 Milter (mail - filter) protocol. When mail is not received via the smtpd(8) server, + filter) protocol. When mail is not received via the smtpd(8) server, the cleanup(8) server will simulate SMTP events to the extent that this is possible. For details see the MILTER_README document. non_smtpd_milters (empty) - A list of Milter (mail filter) applications for new mail that + A list of Milter (mail filter) applications for new mail that does not arrive via the Postfix smtpd(8) server. milter_protocol (6) - The mail filter protocol version and optional protocol exten- - sions for communication with a Milter application; prior to + The mail filter protocol version and optional protocol exten- + sions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. milter_default_action (tempfail) - The default action when a Milter (mail filter) response is - unavailable (for example, bad Postfix configuration or Milter + The default action when a Milter (mail filter) response is + unavailable (for example, bad Postfix configuration or Milter failure). milter_macro_daemon_name ($myhostname) - The {daemon_name} macro value for Milter (mail filter) applica- + The {daemon_name} macro value for Milter (mail filter) applica- tions. milter_macro_v ($mail_name $mail_version) @@ -202,45 +202,45 @@ CLEANUP(8) CLEANUP(8) tion, and for negotiating protocol options. milter_command_timeout (30s) - The time limit for sending an SMTP command to a Milter (mail + The time limit for sending an SMTP command to a Milter (mail filter) application, and for receiving the response. milter_content_timeout (300s) - The time limit for sending message content to a Milter (mail + The time limit for sending message content to a Milter (mail filter) application, and for receiving the response. milter_connect_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after completion of an SMTP connection. milter_helo_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the SMTP HELO or EHLO command. milter_mail_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the SMTP MAIL FROM command. milter_rcpt_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the SMTP RCPT TO command. milter_data_macros (see 'postconf -d' output) - The macros that are sent to version 4 or higher Milter (mail + The macros that are sent to version 4 or higher Milter (mail filter) applications after the SMTP DATA command. milter_unknown_command_macros (see 'postconf -d' output) - The macros that are sent to version 3 or higher Milter (mail + The macros that are sent to version 3 or higher Milter (mail filter) applications after an unknown SMTP command. milter_end_of_data_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the message end-of-data. Available in Postfix version 2.5 and later: milter_end_of_header_macros (see 'postconf -d' output) - The macros that are sent to Milter (mail filter) applications + The macros that are sent to Milter (mail filter) applications after the end of the message header. Available in Postfix version 2.7 and later: @@ -252,8 +252,8 @@ CLEANUP(8) CLEANUP(8) Available in Postfix version 3.1 and later: milter_macro_defaults (empty) - Optional list of name=value pairs that specify default values - for arbitrary macros that Postfix may send to Milter applica- + Optional list of name=value pairs that specify default values + for arbitrary macros that Postfix may send to Milter applica- tions. MIME PROCESSING CONTROLS @@ -279,82 +279,83 @@ CLEANUP(8) CLEANUP(8) ing information. strict_mime_encoding_domain (no) - Reject mail with invalid Content-Transfer-Encoding: information + Reject mail with invalid Content-Transfer-Encoding: information for the message/* or multipart/* MIME content types. Available in Postfix version 2.5 and later: detect_8bit_encoding_header (yes) - Automatically detect 8BITMIME body content by looking at Con- - tent-Transfer-Encoding: message headers; historically, this + Automatically detect 8BITMIME body content by looking at Con- + tent-Transfer-Encoding: message headers; historically, this behavior was hard-coded to be "always on". AUTOMATIC BCC RECIPIENT CONTROLS - Postfix can automatically add BCC (blind carbon copy) when mail enters + Postfix can automatically add BCC (blind carbon copy) when mail enters the mail system: always_bcc (empty) - Optional address that receives a "blind carbon copy" of each + Optional address that receives a "blind carbon copy" of each message that is received by the Postfix mail system. Available in Postfix version 2.1 and later: sender_bcc_maps (empty) - Optional BCC (blind carbon-copy) address lookup tables, indexed - by sender address. + Optional BCC (blind carbon-copy) address lookup tables, indexed + by envelope sender address. recipient_bcc_maps (empty) - Optional BCC (blind carbon-copy) address lookup tables, indexed - by recipient address. + Optional BCC (blind carbon-copy) address lookup tables, indexed + by envelope recipient address. ADDRESS TRANSFORMATION CONTROLS - Address rewriting is delegated to the trivial-rewrite(8) daemon. The + Address rewriting is delegated to the trivial-rewrite(8) daemon. The cleanup(8) server implements table driven address mapping. empty_address_recipient (MAILER-DAEMON) The recipient of mail addressed to the null address. canonical_maps (empty) - Optional address mapping lookup tables for message headers and + Optional address mapping lookup tables for message headers and envelopes. recipient_canonical_maps (empty) - Optional address mapping lookup tables for envelope and header + Optional address mapping lookup tables for envelope and header recipient addresses. sender_canonical_maps (empty) - Optional address mapping lookup tables for envelope and header + Optional address mapping lookup tables for envelope and header sender addresses. masquerade_classes (envelope_sender, header_sender, header_recipient) What addresses are subject to address masquerading. masquerade_domains (empty) - Optional list of domains whose subdomain structure will be + Optional list of domains whose subdomain structure will be stripped off in email addresses. masquerade_exceptions (empty) - Optional list of user names that are not subjected to address - masquerading, even when their addresses match $masquer- + Optional list of user names that are not subjected to address + masquerading, even when their addresses match $masquer- ade_domains. propagate_unmatched_extensions (canonical, virtual) - What address lookup tables copy an address extension from the + What address lookup tables copy an address extension from the lookup key to the lookup result. Available before Postfix version 2.0: virtual_maps (empty) - Optional lookup tables with a) names of domains for which all - addresses are aliased to addresses in other local or remote + 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 remote domains. Available in Postfix version 2.0 and later: virtual_alias_maps ($virtual_maps) - Optional lookup tables that alias specific mail addresses or - domains to other local or remote address. + Optional lookup tables with aliases that apply to all recipi- + ents: local(8), virtual, and remote; this is unlike alias_maps + that apply only to local(8) recipients. Available in Postfix version 2.2 and later: @@ -371,9 +372,11 @@ CLEANUP(8) CLEANUP(8) ping. remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and - append the specified domain name to incomplete addresses. + Rewrite or add message headers in mail from remote clients if + the remote_header_rewrite_domain parameter value is non-empty, + updating incomplete addresses with the domain specified in the + remote_header_rewrite_domain parameter, and adding missing head- + ers. RESOURCE AND RATE CONTROLS duplicate_filter_limit (1000) @@ -433,7 +436,7 @@ CLEANUP(8) CLEANUP(8) smtputf8_enable (yes) Enable preliminary SMTPUTF8 support for the protocols described - in RFC 6531..6533. + in RFC 6531, RFC 6532, and RFC 6533. smtputf8_autodetect_classes (sendmail, verify) Detect that a message requires SMTPUTF8 support for the speci- @@ -520,6 +523,13 @@ CLEANUP(8) CLEANUP(8) The email address form that will be used in non-debug logging (info, warning, etc.). + Available in Postfix 3.9 and later: + + force_mime_input_conversion (no) + Convert body content that claims to be 8-bit into quoted-print- + able, before header_checks, body_checks, Milters, and before + after-queue content filters. + FILES /etc/postfix/canonical*, canonical mapping table /etc/postfix/virtual*, virtual mapping table diff --git a/html/dnsblog.8.html b/html/dnsblog.8.html index 250b046..2028fa1 100644 --- a/html/dnsblog.8.html +++ b/html/dnsblog.8.html @@ -49,8 +49,8 @@ DNSBLOG(8) DNSBLOG(8) request before it is terminated by a built-in watchdog timer. postscreen_dnsbl_sites (empty) - Optional list of DNS allow/denylist domains, filters and weight - factors. + Optional list of patterns with DNS allow/denylist domains, fil- + ters and weight factors. ipc_timeout (3600s) The time limit for sending or receiving information over an diff --git a/html/generic.5.html b/html/generic.5.html index 813d47e..c1a8a30 100644 --- a/html/generic.5.html +++ b/html/generic.5.html @@ -182,25 +182,26 @@ GENERIC(5) GENERIC(5) Other parameters of interest: inet_interfaces (all) - The network interface addresses that this mail system receives - mail on. + The local network interface addresses that this mail system + receives mail on. proxy_interfaces (empty) - The network interface addresses that this mail system receives - mail on by way of a proxy or network address translation unit. + The remote network interface addresses that this mail system + receives mail on by way of a proxy or network address transla- + tion unit. mydestination ($myhostname, localhost.$mydomain, localhost) - The list of domains that are delivered via the $local_transport + The list of domains that are delivered via the $local_transport mail delivery transport. myorigin ($myhostname) - The domain name that locally-posted mail appears to come from, + The domain name that locally-posted mail appears to come from, and that locally posted mail is delivered to. owner_request_special (yes) - Enable special treatment for owner-listname entries in the + Enable special treatment for owner-listname entries in the aliases(5) file, and don't split owner-listname and list- - name-request address localparts when the recipient_delimiter is + name-request address localparts when the recipient_delimiter is set to "-". SEE ALSO diff --git a/html/header_checks.5.html b/html/header_checks.5.html index 6bb114a..c1c8b17 100644 --- a/html/header_checks.5.html +++ b/html/header_checks.5.html @@ -392,40 +392,31 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) Return-Path:. CONFIGURATION PARAMETERS - body_checks - Lookup tables with content filter rules for message body lines. - These filters see one physical line at a time, in chunks of at - most $line_length_limit bytes. - - body_checks_size_limit - The amount of content per message body segment (attachment) that - is subjected to $body_checks filtering. - - header_checks - - mime_header_checks (default: $header_checks) - - nested_header_checks (default: $header_checks) - Lookup tables with content filter rules for message header - lines: respectively, these are applied to the initial message - headers (not including MIME headers), to the MIME headers any- - where in the message, and to the initial headers of attached - messages. - - Note: these filters see one logical message header at a time, - even when a message header spans multiple lines. Message headers - that are longer than $header_size_limit characters are trun- - cated. - - disable_mime_input_processing - While receiving mail, give no special treatment to MIME related - message headers; all text after the initial message headers is - considered to be part of the message body. This means that - header_checks is applied to all the initial message headers, and - that body_checks is applied to the remainder of the message. - - Note: when used in this manner, body_checks will process a - multi-line message header one line at a time. + body_checks (empty) + Optional lookup tables for content inspection as specified in + the body_checks(5) manual page. + + body_checks_size_limit (51200) + How much text in a message body segment (or attachment, if you + prefer to use that term) is subjected to body_checks inspection. + + header_checks (empty) + Optional lookup tables for content inspection of primary + non-MIME message headers, as specified in the header_checks(5) + manual page. + + mime_header_checks ($header_checks) + Optional lookup tables for content inspection of MIME related + message headers, as described in the header_checks(5) manual + page. + + nested_header_checks ($header_checks) + Optional lookup tables for content inspection of non-MIME mes- + sage headers in attached messages, as described in the + header_checks(5) manual page. + + disable_mime_input_processing (no) + Turn off MIME processing while receiving mail. EXAMPLES Header pattern to block attachments with bad file name extensions. For diff --git a/html/index.html b/html/index.html index 68edc59..a7da6cb 100644 --- a/html/index.html +++ b/html/index.html @@ -53,6 +53,8 @@ configuration examples
    • Backwards-Compatibility Safety Net +
    • Deprecated features and alternatives +
    • Installation from source code @@ -141,6 +143,8 @@ Per-client/user/etc. access
    • Memcache Howto +
    • MongoDB Howto +
    • MySQL Howto
    • PCRE Howto diff --git a/html/lmtp.8.html b/html/lmtp.8.html index 1144ee8..4cc187c 100644 --- a/html/lmtp.8.html +++ b/html/lmtp.8.html @@ -5,88 +5,100 @@ Postfix manual - smtp(8)
      -SMTP(8)                                                                SMTP(8)
      +SMTP,(LMTP)                                                        SMTP,(LMTP)
       
       NAME
      -       smtp - Postfix SMTP+LMTP client
      +       smtp, lmtp - Postfix SMTP+LMTP client
       
       SYNOPSIS
              smtp [generic Postfix daemon options] [flags=DORX]
       
      +       lmtp [generic Postfix daemon options] [flags=DORX]
      +
       DESCRIPTION
              The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery
              protocols. It processes message delivery requests from the  queue  man-
              ager.  Each  request specifies a queue file, a sender address, a domain
              or host to deliver to, and recipient information.  This program expects
      -       to be run from the master(8) process manager.
      +       to be run from the master(8) process manager. The process name, smtp or
      +       lmtp, controls the protocol, and the names of the configuration parame-
      +       ters that will be used.
       
              The  SMTP+LMTP  client  updates  the queue file and marks recipients as
              finished, or it informs the queue manager that delivery should be tried
              again  at  a  later  time.  Delivery  status  reports  are  sent to the
              bounce(8), defer(8) or trace(8) daemon as appropriate.
       
      -       The SMTP+LMTP client looks up a list of mail  exchanger  addresses  for
      -       the  destination  host,  sorts  the list by preference, and connects to
      -       each listed address until it finds a server that responds.
      -
      -       When a server is not reachable, or when mail delivery fails  due  to  a
      -       recoverable  error  condition, the SMTP+LMTP client will try to deliver
      -       the mail to an alternate host.
      +       The server lookup strategy is different for SMTP and LMTP, as described
      +       in the sections "SMTP SERVER LOOKUP" and "LMTP SERVER LOOKUP".
       
      -       After a successful mail transaction, a connection may be saved  to  the
      -       scache(8)  connection  cache  server,  so  that  it  may be used by any
      +       After  a  successful mail transaction, a connection may be saved to the
      +       scache(8) connection cache server, so  that  it  may  be  used  by  any
              SMTP+LMTP client for a subsequent transaction.
       
      -       By default, connection caching is enabled temporarily for  destinations
      +       By  default, connection caching is enabled temporarily for destinations
              that have a high volume of mail in the active queue. Connection caching
              can be enabled permanently for specific destinations.
       
      -SMTP DESTINATION SYNTAX
      -       The Postfix SMTP+LMTP client supports multiple  destinations  separated
      -       by comma or whitespace (Postfix 3.5 and later).  SMTP destinations have
      -       the following form:
      +SMTP SERVER LOOKUP
      +       The  Postfix  SMTP  client  supports multiple destinations separated by
      +       comma or whitespace (Postfix 3.5 and later).  Each destination is tried
      +       in the specified order.
      +
      +       SMTP destinations have the following form:
       
              domainname
       
      -       domainname:port
      -              Look up the mail exchangers for the specified domain,  and  con-
      -              nect to the specified port (default: smtp).
      +       domainname:service
      +              Look  up  the mail exchangers for the specified domain, and con-
      +              nect to the specified service (default: smtp).  Optionally, mail
      +              exchangers may be looked up with SRV queries instead of MX; this
      +              requires that service is given in symbolic form.
       
              [hostname]
       
      -       [hostname]:port
      -              Look  up  the  address(es) of the specified host, and connect to
      -              the specified port (default: smtp).
      +       [hostname]:service
      +              Look up the address(es) for the specified host, and  connect  to
      +              the specified service (default: smtp).
       
              [address]
       
      -       [address]:port
      +       [address]:service
                     Connect to the host at the specified address, and connect to the
      -              specified  port (default: smtp). An IPv6 address must be format-
      -              ted as [ipv6:address].
      +              specified service (default: smtp). An IPv6 address must be  for-
      +              matted as [ipv6:address].
       
      -LMTP DESTINATION SYNTAX
      -       The Postfix SMTP+LMTP client supports multiple  destinations  separated
      -       by comma or whitespace (Postfix 3.5 and later).  LMTP destinations have
      -       the following form:
      +LMTP SERVER LOOKUP
      +       The  Postfix  LMTP  client  supports multiple destinations separated by
      +       comma or whitespace (Postfix 3.5 and later).  Each destination is tried
      +       in the specified order.
      +
      +       LMTP destinations have the following form:
       
              unix:pathname
      -              Connect to the local UNIX-domain server that  is  bound  to  the
      -              specified  pathname.  If  the process runs chrooted, an absolute
      +              Connect  to  the  local  UNIX-domain server that is bound to the
      +              specified pathname. If the process runs  chrooted,  an  absolute
                     pathname is interpreted relative to the Postfix queue directory.
       
      +       inet:domainname
      +
      +       inet:domainname:service
      +              Look up the LMTP servers for the specified  domain  and  service
      +              (default:  lmtp).   This  form is supported when SRV lookups are
      +              enabled, and requires that service is in symbolic form.
      +
              inet:hostname
       
      -       inet:hostname:port
      +       inet:hostname:service
      +              Look up the address(es) for the specified host, and  connect  to
      +              the  specified  service  (default:  lmtp).  When SRV lookups are
      +              enabled, use the form [hostname] to force address lookups.
       
              inet:[address]
       
      -       inet:[address]:port
      -              Connect  to  the  specified  TCP  port on the specified local or
      -              remote host. If no  port  is  specified,  connect  to  the  port
      -              defined  as  lmtp  in services(4).  If no such service is found,
      -              the lmtp_tcp_port configuration parameter (default value of  24)
      -              will   be   used.    An   IPv6  address  must  be  formatted  as
      +       inet:[address]:service
      +              Connect to the  specified  local  or  remote  host  and  service
      +              (default:   lmtp).    An  IPv6  address  must  be  formatted  as
                     [ipv6:address].
       
       SINGLE-RECIPIENT DELIVERY
      @@ -136,10 +148,9 @@ SMTP(8)                                                                SMTP(8)
                            This feature is available as of Postfix 3.5.
       
       SECURITY
      -       The SMTP+LMTP client is moderately security-sensitive. It
      -       talks to SMTP or LMTP servers and to DNS servers on the
      -       network. The SMTP+LMTP client can be run chrooted at fixed
      -       low privilege.
      +       The SMTP+LMTP client is moderately security-sensitive. It talks to SMTP
      +       or LMTP servers and to DNS servers on the network. The SMTP+LMTP client
      +       can be run chrooted at fixed low privilege.
       
       STANDARDS
              RFC 821 (SMTP protocol)
      @@ -180,20 +191,19 @@ SMTP(8)                                                                SMTP(8)
              for all destinations that map onto the same IP address and TCP port.
       
       CONFIGURATION PARAMETERS
      -       Before Postfix version 2.3, the LMTP client is a separate program  that
      -       implements  only  a  subset  of  the functionality available with SMTP:
      -       there is no support for TLS, and  connections  are  cached  in-process,
      -       making it ineffective when the client is used for multiple domains.
      +       Postfix versions 2.3 and later implement the SMTP and LMTP client  with
      +       the  same program, and choose the protocol and configuration parameters
      +       based on the process name, smtp or lmtp.
       
              Most smtp_xxx configuration parameters have an lmtp_xxx "mirror" param-
      -       eter for the equivalent LMTP  feature.  This  document  describes  only
      +       eter  for  the  equivalent  LMTP  feature. This document describes only
              those LMTP-related parameters that aren't simply "mirror" parameters.
       
      -       Changes  to  main.cf  are picked up automatically, as smtp(8) processes
      +       Changes to main.cf are picked up automatically,  as  smtp(8)  processes
              run for only a limited amount of time. Use the command "postfix reload"
              to speed up a change.
       
      -       The  text  below provides only a parameter summary. See postconf(5) for
      +       The text below provides only a parameter summary. See  postconf(5)  for
              more details including examples.
       
       COMPATIBILITY CONTROLS
      @@ -214,8 +224,8 @@ SMTP(8)                                                                SMTP(8)
                     will send via SMTP.
       
              smtp_pix_workaround_delay_time (10s)
      -              How  long  the  Postfix  SMTP  client  pauses   before   sending
      -              ".<CR><LF>"   in   order   to   work  around  the  PIX  firewall
      +              How   long   the  Postfix  SMTP  client  pauses  before  sending
      +              ".<CR><LF>"  in  order  to  work   around   the   PIX   firewall
                     "<CR><LF>.<CR><LF>" bug.
       
              smtp_pix_workaround_threshold_time (500s)
      @@ -224,19 +234,19 @@ SMTP(8)                                                                SMTP(8)
                     delivery through firewalls with "smtp fixup" mode turned on.
       
              smtp_pix_workarounds (disable_esmtp, delay_dotcrlf)
      -              A list that specifies zero or more  workarounds  for  CISCO  PIX
      +              A  list  that  specifies  zero or more workarounds for CISCO PIX
                     firewall bugs.
       
              smtp_pix_workaround_maps (empty)
      -              Lookup  tables,  indexed by the remote SMTP server address, with
      +              Lookup tables, indexed by the remote SMTP server  address,  with
                     per-destination workarounds for CISCO PIX firewall bugs.
       
              smtp_quote_rfc821_envelope (yes)
      -              Quote addresses in Postfix SMTP client MAIL  FROM  and  RCPT  TO
      +              Quote  addresses  in  Postfix  SMTP client MAIL FROM and RCPT TO
                     commands as required by RFC 5321.
       
              smtp_reply_filter (empty)
      -              A  mechanism  to  transform replies from remote SMTP servers one
      +              A mechanism to transform replies from remote  SMTP  servers  one
                     line at a time.
       
              smtp_skip_5xx_greeting (yes)
      @@ -248,68 +258,68 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.0 and earlier:
       
              smtp_skip_4xx_greeting (yes)
      -              Skip SMTP servers that greet with a 4XX status  code  (go  away,
      +              Skip  SMTP  servers  that greet with a 4XX status code (go away,
                     try again later).
       
              Available in Postfix version 2.2 and later:
       
              smtp_discard_ehlo_keyword_address_maps (empty)
      -              Lookup  tables,  indexed by the remote SMTP server address, with
      -              case insensitive lists of EHLO keywords  (pipelining,  starttls,
      +              Lookup tables, indexed by the remote SMTP server  address,  with
      +              case  insensitive  lists of EHLO keywords (pipelining, starttls,
                     auth, etc.) that the Postfix SMTP client will ignore in the EHLO
                     response from a remote SMTP server.
       
              smtp_discard_ehlo_keywords (empty)
      -              A case insensitive list of EHLO keywords (pipelining,  starttls,
      +              A  case insensitive list of EHLO keywords (pipelining, starttls,
                     auth, etc.) that the Postfix SMTP client will ignore in the EHLO
                     response from a remote SMTP server.
       
              smtp_generic_maps (empty)
      -              Optional lookup tables that perform  address  rewriting  in  the
      -              Postfix  SMTP  client,  typically  to  transform a locally valid
      -              address into a globally valid address when sending  mail  across
      +              Optional  lookup  tables  that  perform address rewriting in the
      +              Postfix SMTP client, typically  to  transform  a  locally  valid
      +              address  into  a globally valid address when sending mail across
                     the Internet.
       
              Available in Postfix version 2.2.9 and later:
       
              smtp_cname_overrides_servername (version dependent)
      -              When  the  remote  SMTP  servername  is a DNS CNAME, replace the
      -              servername with the result from CNAME expansion for the  purpose
      -              of  logging,  SASL password lookup, TLS policy decisions, or TLS
      +              When the remote SMTP servername is  a  DNS  CNAME,  replace  the
      +              servername  with the result from CNAME expansion for the purpose
      +              of logging, SASL password lookup, TLS policy decisions,  or  TLS
                     certificate verification.
       
              Available in Postfix version 2.3 and later:
       
              lmtp_discard_lhlo_keyword_address_maps (empty)
      -              Lookup tables, indexed by the remote LMTP server  address,  with
      -              case  insensitive  lists of LHLO keywords (pipelining, starttls,
      +              Lookup  tables,  indexed by the remote LMTP server address, with
      +              case insensitive lists of LHLO keywords  (pipelining,  starttls,
                     auth, etc.) that the Postfix LMTP client will ignore in the LHLO
                     response from a remote LMTP server.
       
              lmtp_discard_lhlo_keywords (empty)
      -              A  case insensitive list of LHLO keywords (pipelining, starttls,
      +              A case insensitive list of LHLO keywords (pipelining,  starttls,
                     auth, etc.) that the Postfix LMTP client will ignore in the LHLO
                     response from a remote LMTP server.
       
              Available in Postfix version 2.4.4 and later:
       
              send_cyrus_sasl_authzid (no)
      -              When  authenticating  to  a  remote SMTP or LMTP server with the
      -              default setting "no", send no SASL authoriZation  ID  (authzid);
      -              send  only  the  SASL authentiCation ID (authcid) plus the auth-
      +              When authenticating to a remote SMTP or  LMTP  server  with  the
      +              default  setting  "no", send no SASL authoriZation ID (authzid);
      +              send only the SASL authentiCation ID (authcid)  plus  the  auth-
                     cid's password.
       
              Available in Postfix version 2.5 and later:
       
              smtp_header_checks (empty)
      -              Restricted header_checks(5) tables for the Postfix SMTP  client.
      +              Restricted  header_checks(5) tables for the Postfix SMTP client.
       
              smtp_mime_header_checks (empty)
      -              Restricted  mime_header_checks(5)  tables  for  the Postfix SMTP
      +              Restricted mime_header_checks(5) tables  for  the  Postfix  SMTP
                     client.
       
              smtp_nested_header_checks (empty)
      -              Restricted nested_header_checks(5) tables for the  Postfix  SMTP
      +              Restricted  nested_header_checks(5)  tables for the Postfix SMTP
                     client.
       
              smtp_body_checks (empty)
      @@ -318,7 +328,7 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.6 and later:
       
              tcp_windowsize (0)
      -              An  optional  workaround for routers that break TCP window scal-
      +              An optional workaround for routers that break TCP  window  scal-
                     ing.
       
              Available in Postfix version 2.8 and later:
      @@ -329,16 +339,16 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.9 - 3.6:
       
              smtp_per_record_deadline (no)
      -              Change the behavior of the smtp_*_timeout time  limits,  from  a
      -              time  limit  per  read  or write system call, to a time limit to
      -              send or receive a complete record (an SMTP  command  line,  SMTP
      -              response  line,  SMTP message content line, or TLS protocol mes-
      +              Change  the  behavior  of the smtp_*_timeout time limits, from a
      +              time limit per read or write system call, to  a  time  limit  to
      +              send  or  receive  a complete record (an SMTP command line, SMTP
      +              response line, SMTP message content line, or TLS  protocol  mes-
                     sage).
       
              Available in Postfix version 2.9 and later:
       
              smtp_send_dummy_mail_auth (no)
      -              Whether or not to append the "AUTH=<>" option to the  MAIL  FROM
      +              Whether  or  not to append the "AUTH=<>" option to the MAIL FROM
                     command in SASL-authenticated SMTP sessions.
       
              Available in Postfix version 2.11 and later:
      @@ -349,7 +359,7 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 3.0 and later:
       
              smtp_delivery_status_filter ($default_delivery_status_filter)
      -              Optional  filter  for  the  smtp(8) delivery agent to change the
      +              Optional filter for the smtp(8) delivery  agent  to  change  the
                     delivery status code or explanatory text of successful or unsuc-
                     cessful deliveries.
       
      @@ -359,38 +369,38 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 3.3 and later:
       
              smtp_balance_inet_protocols (yes)
      -              When  a remote destination resolves to a combination of IPv4 and
      +              When a remote destination resolves to a combination of IPv4  and
                     IPv6 addresses, ensure that the Postfix SMTP client can try both
                     address types before it runs into the smtp_mx_address_limit.
       
              Available in Postfix 3.5 and later:
       
              info_log_address_format (external)
      -              The  email  address  form that will be used in non-debug logging
      +              The email address form that will be used  in  non-debug  logging
                     (info, warning, etc.).
       
              Available in Postfix 3.6 and later:
       
              dnssec_probe (ns:.)
      -              The DNS query type (default: "ns") and DNS query name  (default:
      +              The  DNS query type (default: "ns") and DNS query name (default:
                     ".") that Postfix may use to determine whether DNSSEC validation
                     is available.
       
      -       known_tcp_ports  (lmtp=24,  smtp=25,   smtps=submissions=465,   submis-
      +       known_tcp_ports   (lmtp=24,   smtp=25,  smtps=submissions=465,  submis-
              sion=587)
      -              Optional setting that avoids lookups in  the  services(5)  data-
      +              Optional  setting  that  avoids lookups in the services(5) data-
                     base.
       
              Available in Postfix version 3.7 and later:
       
              smtp_per_request_deadline (no)
      -              Change  the  behavior  of the smtp_*_timeout time limits, from a
      -              time limit per plaintext or TLS read or write call,  to  a  com-
      -              bined  time  limit  for  sending a complete SMTP request and for
      +              Change the behavior of the smtp_*_timeout time  limits,  from  a
      +              time  limit  per  plaintext or TLS read or write call, to a com-
      +              bined time limit for sending a complete  SMTP  request  and  for
                     receiving a complete SMTP response.
       
              smtp_min_data_rate (500)
      -              The minimum plaintext data transfer  rate  in  bytes/second  for
      +              The  minimum  plaintext  data  transfer rate in bytes/second for
                     DATA    requests,    when    deadlines    are    enabled    with
                     smtp_per_request_deadline.
       
      @@ -400,16 +410,16 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 3.8 and later:
       
              use_srv_lookup (empty)
      -              Enables discovery for the specified  service(s)  using  DNS  SRV
      +              Enables  discovery  for  the  specified service(s) using DNS SRV
                     records.
       
              ignore_srv_lookup_error (no)
      -              When  SRV  record  lookup  fails,  fall back to MX or IP address
      +              When SRV record lookup fails, fall back  to  MX  or  IP  address
                     lookup as if SRV record lookup was not enabled.
       
              allow_srv_lookup_fallback (no)
      -              When SRV record lookup fails or no SRV record exists, fall  back
      -              to  MX  or  IP  address  lookup  as if SRV record lookup was not
      +              When  SRV record lookup fails or no SRV record exists, fall back
      +              to MX or IP address lookup as  if  SRV  record  lookup  was  not
                     enabled.
       
       MIME PROCESSING CONTROLS
      @@ -428,7 +438,7 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.1 and later:
       
              smtp_send_xforward_command (no)
      -              Send  the  non-standard  XFORWARD  command when the Postfix SMTP
      +              Send the non-standard XFORWARD command  when  the  Postfix  SMTP
                     server EHLO response announces XFORWARD support.
       
       SASL AUTHENTICATION CONTROLS
      @@ -436,60 +446,66 @@ SMTP(8)                                                                SMTP(8)
                     Enable SASL authentication in the Postfix SMTP client.
       
              smtp_sasl_password_maps (empty)
      -              Optional Postfix  SMTP  client  lookup  tables  with  one  user-
      -              name:password  entry  per  sender,  remote  hostname or next-hop
      +              Optional  Postfix  SMTP  client  lookup  tables  with  one user-
      +              name:password entry per  sender,  remote  hostname  or  next-hop
                     domain.
       
              smtp_sasl_security_options (noplaintext, noanonymous)
                     Postfix SMTP client SASL security options; as of Postfix 2.3 the
      -              list  of available features depends on the SASL client implemen-
      +              list of available features depends on the SASL client  implemen-
                     tation that is selected with smtp_sasl_type.
       
              Available in Postfix version 2.2 and later:
       
              smtp_sasl_mechanism_filter (empty)
      -              If non-empty, a Postfix SMTP client filter for the  remote  SMTP
      +              If  non-empty,  a Postfix SMTP client filter for the remote SMTP
                     server's list of offered SASL mechanisms.
       
              Available in Postfix version 2.3 and later:
       
              smtp_sender_dependent_authentication (no)
                     Enable  sender-dependent  authentication  in  the  Postfix  SMTP
      -              client; this is available only  with  SASL  authentication,  and
      -              disables  SMTP  connection caching to ensure that mail from dif-
      +              client;  this  is  available  only with SASL authentication, and
      +              disables SMTP connection caching to ensure that mail  from  dif-
                     ferent senders will use the appropriate credentials.
       
              smtp_sasl_path (empty)
                     Implementation-specific information that the Postfix SMTP client
      -              passes  through  to  the  SASL  plug-in  implementation  that is
      +              passes through  to  the  SASL  plug-in  implementation  that  is
                     selected with smtp_sasl_type.
       
              smtp_sasl_type (cyrus)
      -              The SASL plug-in type that the Postfix SMTP  client  should  use
      +              The  SASL  plug-in  type that the Postfix SMTP client should use
                     for authentication.
       
              Available in Postfix version 2.5 and later:
       
              smtp_sasl_auth_cache_name (empty)
      -              An  optional table to prevent repeated SASL authentication fail-
      -              ures with the same remote SMTP  server  hostname,  username  and
      +              An optional table to prevent repeated SASL authentication  fail-
      +              ures  with  the  same  remote SMTP server hostname, username and
                     password.
       
              smtp_sasl_auth_cache_time (90d)
      -              The  maximal age of an smtp_sasl_auth_cache_name entry before it
      +              The maximal age of an smtp_sasl_auth_cache_name entry before  it
                     is removed.
       
              smtp_sasl_auth_soft_bounce (yes)
      -              When a remote SMTP server rejects a SASL authentication  request
      -              with  a 535 reply code, defer mail delivery instead of returning
      +              When  a remote SMTP server rejects a SASL authentication request
      +              with a 535 reply code, defer mail delivery instead of  returning
                     mail as undeliverable.
       
              Available in Postfix version 2.9 and later:
       
              smtp_send_dummy_mail_auth (no)
      -              Whether or not to append the "AUTH=<>" option to the  MAIL  FROM
      +              Whether  or  not to append the "AUTH=<>" option to the MAIL FROM
                     command in SASL-authenticated SMTP sessions.
       
      +       Available in Postfix version 3.9 and later:
      +
      +       smtp_sasl_password_result_delimiter (:)
      +              The delimiter between username and password in  sasl_passwd_maps
      +              lookup results.
      +
       STARTTLS SUPPORT CONTROLS
              Detailed  information  about STARTTLS configuration may be found in the
              TLS_README document.
      @@ -619,7 +635,7 @@ SMTP(8)                                                                SMTP(8)
       
              Available in Postfix version 2.6 and later:
       
      -       smtp_tls_protocols (see postconf -d output)
      +       smtp_tls_protocols (see 'postconf -d' output)
                     TLS  protocols that the Postfix SMTP client will use with oppor-
                     tunistic TLS encryption.
       
      @@ -724,6 +740,12 @@ SMTP(8)                                                                SMTP(8)
                     The application name passed by Postfix to OpenSSL  library  ini-
                     tialization functions.
       
      +       Available in Postfix version 3.9 and later:
      +
      +       smtp_tls_enable_rpk (no)
      +              Request  that remote SMTP servers send an RFC7250 raw public key
      +              instead of an X.509 certificate.
      +
       OBSOLETE STARTTLS CONTROLS
              The following configuration parameters  exist  for  compatibility  with
              Postfix  versions  before  2.3.  Support for these will be removed in a
      @@ -954,7 +976,7 @@ SMTP(8)                                                                SMTP(8)
                     The  local  network  interface  addresses  that this mail system
                     receives mail on.
       
      -       inet_protocols (see 'postconf -d output')
      +       inet_protocols (see 'postconf -d' output)
                     The Internet protocols Postfix will attempt to use  when  making
                     or accepting connections.
       
      @@ -1119,5 +1141,5 @@ SMTP(8)                                                                SMTP(8)
              Victor Duchovni
              Morgan Stanley
       
      -                                                                       SMTP(8)
      +                                       8                           SMTP,(LMTP)
       
      diff --git a/html/local.8.html b/html/local.8.html index fce3d04..a923ce2 100644 --- a/html/local.8.html +++ b/html/local.8.html @@ -178,40 +178,42 @@ LOCAL(8) LOCAL(8) replaced with underscores. The list of acceptable characters is speci- fied with the command_expansion_filter configuration parameter. - SHELL The recipient user's login shell. + SHELL The envelope recipient user's login shell. - HOME The recipient user's home directory. + HOME The envelope recipient user's home directory. - USER The bare recipient name. + USER The bare envelope recipient name. EXTENSION - The optional recipient address extension. + The optional envelope recipient address extension. - DOMAIN The recipient address domain part. + DOMAIN The envelope recipient address domain part. LOGNAME - The bare recipient name. + The bare envelope recipient name. - LOCAL The entire recipient address localpart (text to the left of the - rightmost @ character). + LOCAL The entire envelope recipient address localpart (text to the + left of the rightmost @ character). ORIGINAL_RECIPIENT - The entire recipient address, before any address rewriting or - aliasing (Postfix 2.5 and later). + The entire envelope recipient address, before any address + rewriting or aliasing (Postfix 2.5 and later). RECIPIENT - The entire recipient address. + The entire envelope recipient address. - SENDER The entire sender address. + SENDER The entire envelope sender address. - Additional remote client information is made available via the follow- + ENVID The optional RFC 3461 envelope ID. Available as of Postfix 3.9. + + Additional remote client information is made available via the follow- ing environment variables: CLIENT_ADDRESS Remote client network address. Available as of Postfix 2.2. CLIENT_HELO - Remote client EHLO command parameter. Available as of Postfix + Remote client EHLO command parameter. Available as of Postfix 2.2. CLIENT_HOSTNAME @@ -221,69 +223,69 @@ LOCAL(8) LOCAL(8) Remote client protocol. Available as of Postfix 2.2. SASL_METHOD - SASL authentication method specified in the remote client AUTH + SASL authentication method specified in the remote client AUTH command. Available as of Postfix 2.2. SASL_SENDER - SASL sender address specified in the remote client MAIL FROM + SASL sender address specified in the remote client MAIL FROM command. Available as of Postfix 2.2. SASL_USERNAME - SASL username specified in the remote client AUTH command. + SASL username specified in the remote client AUTH command. Available as of Postfix 2.2. - The PATH environment variable is always reset to a system-dependent - default path, and environment variables whose names are blessed by the + The PATH environment variable is always reset to a system-dependent + default path, and environment variables whose names are blessed by the export_environment configuration parameter are exported unchanged. The current working directory is the mail queue directory. The local(8) daemon prepends a "From sender time_stamp" envelope header - to each message, prepends an X-Original-To: header with the recipient - address as given to Postfix, prepends an optional Delivered-To: header - with the final recipient envelope address, prepends a Return-Path: + to each message, prepends an X-Original-To: header with the recipient + address as given to Postfix, prepends an optional Delivered-To: header + with the final recipient envelope address, prepends a Return-Path: header with the sender envelope address, and appends no empty line. EXTERNAL FILE DELIVERY - The delivery format depends on the destination filename syntax. The - default is to use UNIX-style mailbox format. Specify a name ending in + The delivery format depends on the destination filename syntax. The + default is to use UNIX-style mailbox format. Specify a name ending in / for qmail-compatible maildir delivery. - The allow_mail_to_files configuration parameter restricts delivery to - external files. The default setting (alias, forward) forbids file des- + The allow_mail_to_files configuration parameter restricts delivery to + external files. The default setting (alias, forward) forbids file des- tinations in :include: files. - In the case of UNIX-style mailbox delivery, the local(8) daemon - prepends a "From sender time_stamp" envelope header to each message, - prepends an X-Original-To: header with the recipient address as given - to Postfix, prepends an optional Delivered-To: header with the final - recipient envelope address, prepends a > character to lines beginning - with "From ", and appends an empty line. The envelope sender address - is available in the Return-Path: header. When the destination is a - regular file, it is locked for exclusive access while delivery is in + In the case of UNIX-style mailbox delivery, the local(8) daemon + prepends a "From sender time_stamp" envelope header to each message, + prepends an X-Original-To: header with the recipient address as given + to Postfix, prepends an optional Delivered-To: header with the final + recipient envelope address, prepends a > character to lines beginning + with "From ", and appends an empty line. The envelope sender address + is available in the Return-Path: header. When the destination is a + regular file, it is locked for exclusive access while delivery is in progress. In case of problems, an attempt is made to truncate a regular file to its original length. - In the case of maildir delivery, the local daemon prepends an optional - Delivered-To: header with the final envelope recipient address, and - prepends an X-Original-To: header with the recipient address as given - to Postfix. The envelope sender address is available in the + In the case of maildir delivery, the local daemon prepends an optional + Delivered-To: header with the final envelope recipient address, and + prepends an X-Original-To: header with the recipient address as given + to Postfix. The envelope sender address is available in the Return-Path: header. ADDRESS EXTENSION - The optional recipient_delimiter configuration parameter specifies how + The optional recipient_delimiter configuration parameter specifies how to separate address extensions from local recipient names. - For example, with "recipient_delimiter = +", mail for name+foo is - delivered to the alias name+foo or to the alias name, to the destina- + For example, with "recipient_delimiter = +", mail for name+foo is + delivered to the alias name+foo or to the alias name, to the destina- tions listed in ~name/.forward+foo or in ~name/.forward, to the mailbox owned by the user name, or it is sent back as undeliverable. DELIVERY RIGHTS - Deliveries to external files and external commands are made with the - rights of the receiving user on whose behalf the delivery is made. In - the absence of a user context, the local(8) daemon uses the owner - rights of the :include: file or alias database. When those files are + Deliveries to external files and external commands are made with the + rights of the receiving user on whose behalf the delivery is made. In + the absence of a user context, the local(8) daemon uses the owner + rights of the :include: file or alias database. When those files are owned by the superuser, delivery is made with the rights specified with the default_privs configuration parameter. @@ -292,43 +294,43 @@ LOCAL(8) LOCAL(8) RFC 3463 (Enhanced status codes) DIAGNOSTICS - Problems and transactions are logged to syslogd(8) or postlogd(8). - Corrupted message files are marked so that the queue manager can move + Problems and transactions are logged to syslogd(8) or postlogd(8). + Corrupted message files are marked so that the queue manager can move them to the corrupt queue afterwards. - Depending on the setting of the notify_classes parameter, the postmas- + Depending on the setting of the notify_classes parameter, the postmas- ter is notified of bounces and of other trouble. SECURITY - The local(8) delivery agent needs a dual personality 1) to access the + The local(8) delivery agent needs a dual personality 1) to access the private Postfix queue and IPC mechanisms, 2) to impersonate the recipi- - ent and deliver to recipient-specified files or commands. It is there- + ent and deliver to recipient-specified files or commands. It is there- fore security sensitive. - The local(8) delivery agent disallows regular expression substitution + The local(8) delivery agent disallows regular expression substitution of $1 etc. in alias_maps, because that would open a security hole. - The local(8) delivery agent will silently ignore requests to use the - proxymap(8) server within alias_maps. Instead it will open the table + The local(8) delivery agent will silently ignore requests to use the + proxymap(8) server within alias_maps. Instead it will open the table directly. Before Postfix version 2.2, the local(8) delivery agent will terminate with a fatal error. BUGS - For security reasons, the message delivery status of external commands - or of external files is never checkpointed to file. As a result, the - program may occasionally deliver more than once to a command or exter- + For security reasons, the message delivery status of external commands + or of external files is never checkpointed to file. As a result, the + program may occasionally deliver more than once to a command or exter- nal file. Better safe than sorry. - Mutually-recursive aliases or ~/.forward files are not detected early. - The resulting mail forwarding loop is broken by the use of the Deliv- + Mutually-recursive aliases or ~/.forward files are not detected early. + The resulting mail forwarding loop is broken by the use of the Deliv- ered-To: message header. CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically, as local(8) processes + Changes to main.cf are picked up automatically, as local(8) processes run for only a limited amount of time. Use the command "postfix reload" to speed up a change. - The text below provides only a parameter summary. See postconf(5) for + The text below provides only a parameter summary. See postconf(5) for more details including examples. COMPATIBILITY CONTROLS @@ -336,14 +338,14 @@ LOCAL(8) LOCAL(8) Whether or not to use the local biff service. expand_owner_alias (no) - When delivering to an alias "aliasname" that has an + When delivering to an alias "aliasname" that has an "owner-aliasname" companion alias, set the envelope sender address to the expansion of the "owner-aliasname" alias. owner_request_special (yes) - Enable special treatment for owner-listname entries in the + Enable special treatment for owner-listname entries in the aliases(5) file, and don't split owner-listname and list- - name-request address localparts when the recipient_delimiter is + name-request address localparts when the recipient_delimiter is set to "-". sun_mailtool_compatibility (no) @@ -352,62 +354,64 @@ LOCAL(8) LOCAL(8) Available in Postfix version 2.3 and later: frozen_delivered_to (yes) - Update the local(8) delivery agent's idea of the Delivered-To: - address (see prepend_delivered_header) only once, at the start - of a delivery attempt; do not update the Delivered-To: address + Update the local(8) delivery agent's idea of the Delivered-To: + address (see prepend_delivered_header) only once, at the start + of a delivery attempt; do not update the Delivered-To: address while expanding aliases or .forward files. Available in Postfix version 2.5.3 and later: strict_mailbox_ownership (yes) - Defer delivery when a mailbox file is not owned by its recipi- + Defer delivery when a mailbox file is not owned by its recipi- ent. reset_owner_alias (no) - Reset the local(8) delivery agent's idea of the owner-alias - attribute, when delivering mail to a child alias that does not + Reset the local(8) delivery agent's idea of the owner-alias + attribute, when delivering mail to a child alias that does not have its own owner alias. Available in Postfix version 3.0 and later: local_delivery_status_filter ($default_delivery_status_filter) - Optional filter for the local(8) delivery agent to change the - status code or explanatory text of successful or unsuccessful + Optional filter for the local(8) delivery agent to change the + status code or explanatory text of successful or unsuccessful deliveries. DELIVERY METHOD CONTROLS - The precedence of local(8) delivery methods from high to low is: + The precedence of local(8) delivery methods from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, - mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_direc- + mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_direc- tory, fallback_transport_maps, fallback_transport, and luser_relay. alias_maps (see 'postconf -d' output) - The alias databases that are used for local(8) delivery. + Optional lookup tables with aliases that apply only to local(8) + recipients; this is unlike virtual_alias_maps that apply to all + recipients: local(8), virtual, and remote. forward_path (see 'postconf -d' output) - The local(8) delivery agent search list for finding a .forward + The local(8) delivery agent search list for finding a .forward file with user-specified delivery methods. mailbox_transport_maps (empty) Optional lookup tables with per-recipient message delivery - transports to use for local(8) mailbox delivery, whether or not + transports to use for local(8) mailbox delivery, whether or not the recipients are found in the UNIX passwd database. mailbox_transport (empty) - Optional message delivery transport that the local(8) delivery - agent should use for mailbox delivery to all local recipients, + Optional message delivery transport that the local(8) delivery + agent should use for mailbox delivery to all local recipients, whether or not they are found in the UNIX passwd database. mailbox_command_maps (empty) - Optional lookup tables with per-recipient external commands to + Optional lookup tables with per-recipient external commands to use for local(8) mailbox delivery. mailbox_command (empty) - Optional external command that the local(8) delivery agent + Optional external command that the local(8) delivery agent should use for mailbox delivery. home_mailbox (empty) - Optional pathname of a mailbox file relative to a local(8) + Optional pathname of a mailbox file relative to a local(8) user's home directory. mail_spool_directory (see 'postconf -d' output) @@ -419,17 +423,17 @@ LOCAL(8) LOCAL(8) not find in the aliases(5) or UNIX password database. fallback_transport (empty) - Optional message delivery transport that the local(8) delivery - agent should use for names that are not found in the aliases(5) + Optional message delivery transport that the local(8) delivery + agent should use for names that are not found in the aliases(5) or UNIX password database. luser_relay (empty) - Optional catch-all destination for unknown local(8) recipients. + Optional catch-all destination for unknown local(8) recipients. Available in Postfix version 2.2 and later: command_execution_directory (empty) - The local(8) delivery agent working directory for delivery to + The local(8) delivery agent working directory for delivery to external commands. MAILBOX LOCKING CONTROLS @@ -438,15 +442,15 @@ LOCAL(8) LOCAL(8) mailbox file or bounce(8) logfile. deliver_lock_delay (1s) - The time between attempts to acquire an exclusive lock on a + The time between attempts to acquire an exclusive lock on a mailbox file or bounce(8) logfile. stale_lock_time (500s) - The time after which a stale exclusive mailbox lockfile is + The time after which a stale exclusive mailbox lockfile is removed. mailbox_delivery_lock (see 'postconf -d' output) - How to lock a UNIX-style local(8) mailbox before attempting + How to lock a UNIX-style local(8) mailbox before attempting delivery. RESOURCE AND RATE CONTROLS @@ -459,20 +463,20 @@ LOCAL(8) LOCAL(8) showq(8) queue displays. mailbox_size_limit (51200000) - The maximal size of any local(8) individual mailbox or maildir + The maximal size of any local(8) individual mailbox or maildir file, or zero (no limit). Implemented in the qmgr(8) daemon: local_destination_concurrency_limit (2) - The maximal number of parallel deliveries via the local mail - delivery transport to the same recipient (when "local_destina- - tion_recipient_limit = 1") or the maximal number of parallel + The maximal number of parallel deliveries via the local mail + delivery transport to the same recipient (when "local_destina- + tion_recipient_limit = 1") or the maximal number of parallel deliveries to the same local domain (when "local_destina- tion_recipient_limit > 1"). local_destination_recipient_limit (1) - The maximal number of recipients per message delivery via the + The maximal number of recipients per message delivery via the local mail delivery transport. SECURITY CONTROLS @@ -483,49 +487,49 @@ LOCAL(8) LOCAL(8) Restrict local(8) mail delivery to external files. command_expansion_filter (see 'postconf -d' output) - Restrict the characters that the local(8) delivery agent allows - in $name expansions of $mailbox_command and $command_execu- + Restrict the characters that the local(8) delivery agent allows + in $name expansions of $mailbox_command and $command_execu- tion_directory. default_privs (nobody) - The default rights used by the local(8) delivery agent for + The default rights used by the local(8) delivery agent for delivery to an external file or command. forward_expansion_filter (see 'postconf -d' output) - Restrict the characters that the local(8) delivery agent allows + Restrict the characters that the local(8) delivery agent allows in $name expansions of $forward_path. Available in Postfix version 2.2 and later: execution_directory_expansion_filter (see 'postconf -d' output) - Restrict the characters that the local(8) delivery agent allows + Restrict the characters that the local(8) delivery agent allows in $name expansions of $command_execution_directory. Available in Postfix version 2.5.3 and later: strict_mailbox_ownership (yes) - Defer delivery when a mailbox file is not owned by its recipi- + Defer delivery when a mailbox file is not owned by its recipi- ent. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to handle a + How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log- ging sub-second delay values. export_environment (see 'postconf -d' output) - The list of environment variables that a Postfix process will + The list of environment variables that a Postfix process will export to non-Postfix processes. ipc_timeout (3600s) - The time limit for sending or receiving information over an + The time limit for sending or receiving information over an internal communication channel. local_command_shell (empty) @@ -533,7 +537,7 @@ LOCAL(8) LOCAL(8) mands. max_idle (100s) - The maximum amount of time that an idle Postfix daemon process + The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. max_use (100) @@ -541,8 +545,8 @@ LOCAL(8) LOCAL(8) process will service before terminating voluntarily. prepend_delivered_header (command, file, forward) - The message delivery contexts where the Postfix local(8) deliv- - ery agent prepends a Delivered-To: message header with the + The message delivery contexts where the Postfix local(8) deliv- + ery agent prepends a Delivered-To: message header with the address that the mail was delivered to. process_id (read-only) @@ -552,14 +556,14 @@ LOCAL(8) LOCAL(8) The process name of a Postfix command or daemon process. propagate_unmatched_extensions (canonical, virtual) - What address lookup tables copy an address extension from the + What address lookup tables copy an address extension from the lookup key to the lookup result. queue_directory (see 'postconf -d' output) The location of the Postfix top-level queue directory. recipient_delimiter (empty) - The set of characters that can separate an email address local- + The set of characters that can separate an email address local- part, user name, or a .forward file name from its extension. require_home_directory (no) @@ -570,14 +574,14 @@ LOCAL(8) LOCAL(8) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix version 3.3 and later: enable_original_recipient (yes) - Enable support for the original recipient address after an - address is rewritten to a different address (for example with + Enable support for the original recipient address after an + address is rewritten to a different address (for example with aliasing or with canonical mapping). service_name (read-only) @@ -586,7 +590,7 @@ LOCAL(8) LOCAL(8) Available in Postfix 3.5 and later: info_log_address_format (external) - The email address form that will be used in non-debug logging + The email address form that will be used in non-debug logging (info, warning, etc.). FILES @@ -610,10 +614,10 @@ LOCAL(8) LOCAL(8) The Secure Mailer license must be distributed with this software. HISTORY - The Delivered-To: message header appears in the qmail system by Daniel + The Delivered-To: message header appears in the qmail system by Daniel Bernstein. - The maildir structure appears in the qmail system by Daniel Bernstein. + The maildir structure appears in the qmail system by Daniel Bernstein. AUTHOR(S) Wietse Venema diff --git a/html/mailq.1.html b/html/mailq.1.html index bebc17b..bf6051d 100644 --- a/html/mailq.1.html +++ b/html/mailq.1.html @@ -455,9 +455,11 @@ SENDMAIL(1) SENDMAIL(1) The location of the Postfix top-level queue directory. remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and - append the specified domain name to incomplete addresses. + Rewrite or add message headers in mail from remote clients if + the remote_header_rewrite_domain parameter value is non-empty, + updating incomplete addresses with the domain specified in the + remote_header_rewrite_domain parameter, and adding missing head- + ers. syslog_facility (mail) The syslog facility of Postfix logging. diff --git a/html/makedefs.1.html b/html/makedefs.1.html index 7202a8d..ce67257 100644 --- a/html/makedefs.1.html +++ b/html/makedefs.1.html @@ -34,9 +34,9 @@ MAKEDEFS(1) MAKEDEFS(1) AUXLIBS=object_library... Specifies one or more non-default object libraries. Postfix 3.0 and later specify some of their database library dependencies - with AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB, AUXLIBS_MYSQL, - AUXLIBS_PCRE, AUXLIBS_PGSQL, AUXLIBS_SDBM, and AUXLIBS_SQLITE, - respectively. + with AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB, AUXLIBS_MONGODB, + AUXLIBS_MYSQL, AUXLIBS_PCRE, AUXLIBS_PGSQL, AUXLIBS_SDBM, and + AUXLIBS_SQLITE, respectively. CC=compiler_command Specifies a non-default compiler. On many systems, the default diff --git a/html/master.5.html b/html/master.5.html index 04a0c42..21f2b43 100644 --- a/html/master.5.html +++ b/html/master.5.html @@ -226,10 +226,17 @@ MASTER(5) MASTER(5) options to make a Postfix daemon process increasingly verbose. - Other command-line arguments + Command-line arguments that start with { + With Postfix 3.0 and later specify "{" and "}" around + command arguments that start with "{". The outer "{" and + "}" are removed from the input, together with any leading + or trailing whitespace. + + Other command-line arguments Specify "{" and "}" around command arguments that contain - whitespace (Postfix 3.0 and later). Whitespace after "{" - and before "}" is ignored. + whitespace (Postfix 3.0 and later). The outer "{" and "}" + are removed from the input, together with any leading or + trailing whitespace. SEE ALSO master(8), process manager diff --git a/html/master.8.html b/html/master.8.html index cacc801..de0f9a5 100644 --- a/html/master.8.html +++ b/html/master.8.html @@ -148,15 +148,15 @@ MASTER(8) MASTER(8) invoked with the -D option. inet_interfaces (all) - The network interface addresses that this mail system receives - mail on. + The local network interface addresses that this mail system + receives mail on. - inet_protocols (see 'postconf -d output') + inet_protocols (see 'postconf -d' output) The Internet protocols Postfix will attempt to use when making or accepting connections. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix + The list of environment variables that a privileged Postfix process will import from a non-Postfix parent process, or name=value environment overrides. diff --git a/html/mongodb_table.5.html b/html/mongodb_table.5.html new file mode 100644 index 0000000..b7434f2 --- /dev/null +++ b/html/mongodb_table.5.html @@ -0,0 +1,215 @@ + + + + + Postfix manual - mongodb_table(5) +
      +MONGODB_TABLE(5)                                              MONGODB_TABLE(5)
      +
      +NAME
      +       mongodb_table - Postfix MongoDB client configuration
      +
      +SYNOPSIS
      +       postmap -q "string" mongodb:/etc/postfix/filename
      +
      +       postmap -q - mongodb:/etc/postfix/filename <inputfile
      +
      +DESCRIPTION
      +       The  Postfix  mail system uses optional tables for address rewriting or
      +       mail routing. These tables are usually in dbm or db format.
      +
      +       Alternatively, lookup tables can be specified as MongoDB databases.  In
      +       order to use MongoDB lookups, define a MongoDB source as a lookup table
      +       in main.cf, for example:
      +           alias_maps = mongodb:/etc/postfix/mongodb-aliases.cf
      +
      +       In this example, the file /etc/postfix/mongodb-aliases.cf has the  same
      +       format  as  the  Postfix  main.cf  file, and can specify the parameters
      +       described below. It is also  possible  to  have  the  configuration  in
      +       main.cf; see "OBSOLETE MAIN.CF PARAMETERS" below.
      +
      +       It is strongly recommended to use proxy:mongodb, in order to reduce the
      +       number of database connections. For example:
      +           alias_maps = proxy:mongodb:/etc/postfix/mongodb-aliases.cf
      +
      +       Note: when using proxy:mongodb:/file, the file must be readable by  the
      +       unprivileged  postfix  user (specified with the Postfix mail_owner con-
      +       figuration parameter).
      +
      +MONGODB PARAMETERS
      +       uri    The URI of mongo server/cluster that Postfix will try to connect
      +              to and query from. Please see
      +              https://www.mongodb.com/docs/manual/reference/connection-string/
      +
      +              Example:
      +                  uri = mongodb+srv://user:pass@loclhost:27017/mail
      +
      +       dbname Name of the database to read the information from.  Example:
      +                  dbname = mail
      +
      +       collection
      +              Name  of  the  collection  (table) to read the information from.
      +              Example:
      +                  collection = mailbox
      +
      +       query_filter
      +              The MongoDB query template used to search the database, where %s
      +              is  a substitute for the email address that Postfix is trying to
      +              resolve. Please see:
      +              https://www.mongodb.com/docs/manual/tutorial/query-documents/
      +
      +              Example:
      +                  query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1}
      +
      +              This parameter supports the following '%' expansions:
      +
      +              %%     This is replaced by a literal '%' character.
      +
      +              %s     This is replaced by the input key. The %s must appear  in
      +                     quotes,  because all Postfix queries are strings contain-
      +                     ing (parts from) a domain or email address. Postfix makes
      +                     no numerical queries.
      +
      +              %u     When the input key is an address of the form user@domain,
      +                     %u is replaced by the local part of the address.   Other-
      +                     wise, %u is replaced by the entire search string.
      +
      +              %d     When the input key is an address of the form user@domain,
      +                     %d is replaced by the domain part of the address.
      +
      +              %[1-9] The patterns %1, %2, ... %9 are replaced  by  the  corre-
      +                     sponding  most  significant  component of the input key's
      +                     domain. If the input key is  user@mail.example.com,  then
      +                     %1 is com, %2 is example and %3 is mail.
      +
      +              In  the  above  substitutions,  characters  will  be  quoted  as
      +              required by RFC 4627. For example, each double  quote  or  back-
      +              slash character will be escaped with a backslash characacter.
      +
      +       projection
      +              Advanced MongoDB query projections. Please see:
      +              https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/
      +
      +              o      If projection is non-empty, then result_attribute must be
      +                     empty.
      +
      +              o      This implementation can  extract  information  only  from
      +                     result  fields  that  have  type  string  (UTF8), integer
      +                     (int32, int64) and array. Other  result  fields  will  be
      +                     ignored with a warning. Please see:
      +                     https://mongoc.org/libbson/current/bson_type_t.html
      +
      +              o      As  with  result_attribute, the top-level _id field (type
      +                     OID) is automatically removed from projection results.
      +
      +       result_attribute
      +              Comma or whitespace separated list with the names of  fields  to
      +              be returned in a lookup result.
      +
      +              o      If result_attribute is non-empty, then projection must be
      +                     empty.
      +
      +              o      As with projection, the top-level _id field (type OID) is
      +                     automatically removed from lookup results.
      +
      +       result_format (default: %s)
      +              Format  template  applied  to  the  result  from  projection  or
      +              result_attribute. Most commonly used to append (or prepend) text
      +              to  the result. This parameter supports the following '%' expan-
      +              sions:
      +
      +              %%     This is replaced by a literal '%' character.
      +
      +              %s     This is replaced by the value of  the  result  attribute.
      +                     When result is empty it is skipped.
      +
      +              %u     When the result attribute value is an address of the form
      +                     user@domain, %u is replaced by  the  local  part  of  the
      +                     address.  When  the  result  has an empty localpart it is
      +                     skipped.
      +
      +              %d     When a result attribute value is an address of  the  form
      +                     user@domain,  %d  is  replaced  by the domain part of the
      +                     attribute value. When the result  is  unqualified  it  is
      +                     skipped.
      +
      +              %[SUD1-9]
      +                     The  upper-case  and decimal digit expansions interpolate
      +                     the parts of the input key rather than the result.  Their
      +                     behavior  is  identical to that described with query_fil-
      +                     ter, and in fact  because  the  input  key  is  known  in
      +                     advance,  lookups  whose  key  does  not  contain all the
      +                     information specified in the  result  template  are  sup-
      +                     pressed and return no results.
      +
      +              For example, using "result_format = smtp:[%s]" allows one to use
      +              a mailHost attribute as the basis of a transport(5) table. After
      +              applying  the result format, multiple values are concatenated as
      +              comma separated strings. The expansion_limit parameter explained
      +              below allows one to restrict the number of values in the result,
      +              which is especially useful for maps that should return a  single
      +              value.
      +
      +              The  default value %s specifies that each attribute value should
      +              be used as is.
      +
      +              NOTE: DO NOT put quotes around the result format! The result  is
      +              not a JSON string.
      +
      +       domain (default: no domain list)
      +              This  is a list of domain names, paths to files, or "type:table"
      +              databases. When specified, only fully qualified search keys with
      +              a  *non-empty*  localpart and a matching domain are eligible for
      +              lookup:  'user'  lookups,  bare  domain  lookups  and  "@domain"
      +              lookups  are  not  performed.  This can significantly reduce the
      +              query load on the backend database. Example:
      +                  domain = postfix.org, hash:/etc/postfix/searchdomains
      +
      +       expansion_limit (default: 0)
      +              A limit on the total number of result elements  returned  (as  a
      +              comma separated list) by a lookup against the map.  A setting of
      +              zero disables the limit. Lookups fail with a temporary error  if
      +              the  limit  is  exceeded.  Setting  the  limit to 1 ensures that
      +              lookups do not return multiple values.
      +
      +OBSOLETE MAIN.CF PARAMETERS
      +       MongoDB parameters can also be defined in main.cf. Specify  as  MongoDB
      +       source  a  name  that  doesn't begin with a slash or a dot. The MongoDB
      +       parameters will then be accessible as the name you've given the  source
      +       in  its  definition,  an underscore, and the name of the parameter. For
      +       example, if a map is specified as "mongodb:mongodb_source",  the  "uri"
      +       parameter would be defined in main.cf as "mongodb_source_uri".
      +
      +       Note:  with  this form, passwords are written in main.cf, which is nor-
      +       mally world-readable, and '$' in a mongodb parameter setting  needs  to
      +       be written as '$$'.
      +
      +SEE ALSO
      +       postmap(1), Postfix lookup table maintenance
      +       postconf(5), configuration parameters
      +
      +README FILES
      +       DATABASE_README, Postfix lookup table overview
      +       MONGODB_README, Postfix MONGODB client guide
      +
      +LICENSE
      +       The Secure Mailer license must be distributed with this software.
      +
      +HISTORY
      +       MongoDB support was introduced with Postfix version 3.9.
      +
      +AUTHOR(S)
      +       Hamid Maadani (hamid@dexo.tech)
      +       Dextrous Technologies, LLC
      +
      +       Edited by:
      +       Wietse Venema
      +       porcupine.org
      +
      +       Based on prior work by:
      +       Stephan Ferraro
      +       Aionda GmbH
      +
      +                                                              MONGODB_TABLE(5)
      +
      diff --git a/html/mysql_table.5.html b/html/mysql_table.5.html index 4971e57..5063e65 100644 --- a/html/mysql_table.5.html +++ b/html/mysql_table.5.html @@ -72,56 +72,76 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) dbname The database name on the servers. Example: dbname = customer_database - query The SQL query template used to search the database, where %s is - a substitute for the address Postfix is trying to resolve, e.g. + charset (default: utf8mb4) + The default MySQL client character set; this also implies the + collation order. + + This parameter is available with Postfix 3.9 and later. With + earlier Postfix versions, the default was chosen by the MySQL + implementation (utf8mb4 as of MySQL 8.0, latin1 historically). + + idle_interval (default: 60) + The number of seconds after which an idle database connection + will be closed. + + This feature is available in Postfix 3.9 and later. + + retry_interval (default: 60) + The number of seconds that a database connection will be skipped + after an error. + + This feature is available in Postfix 3.9 and later. + + query The SQL query template used to search the database, where %s is + a substitute for the address Postfix is trying to resolve, e.g. query = SELECT replacement FROM aliases WHERE mailbox = '%s' - By default, every query must return a result set (instead of - storing its results in a table); with "require_result_set = no" - (Postfix 3.2 and later), the absence of a result set is treated + By default, every query must return a result set (instead of + storing its results in a table); with "require_result_set = no" + (Postfix 3.2 and later), the absence of a result set is treated as "not found". This parameter supports the following '%' expansions: %% This is replaced by a literal '%' character. - %s This is replaced by the input key. SQL quoting is used - to make sure that the input key does not add unexpected + %s This is replaced by the input key. SQL quoting is used + to make sure that the input key does not add unexpected metacharacters. %u When the input key is an address of the form user@domain, - %u is replaced by the SQL quoted local part of the - address. Otherwise, %u is replaced by the entire search - string. If the localpart is empty, the query is sup- + %u is replaced by the SQL quoted local part of the + address. Otherwise, %u is replaced by the entire search + string. If the localpart is empty, the query is sup- pressed and returns no results. %d When the input key is an address of the form user@domain, - %d is replaced by the SQL quoted domain part of the - address. Otherwise, the query is suppressed and returns + %d is replaced by the SQL quoted domain part of the + address. Otherwise, the query is suppressed and returns no results. %[SUD] The upper-case equivalents of the above expansions behave - in the query parameter identically to their lower-case - counter-parts. With the result_format parameter (see - below), they expand the input key rather than the result + in the query parameter identically to their lower-case + counter-parts. With the result_format parameter (see + below), they expand the input key rather than the result value. - %[1-9] The patterns %1, %2, ... %9 are replaced by the corre- - sponding most significant component of the input key's - domain. If the input key is user@mail.example.com, then + %[1-9] The patterns %1, %2, ... %9 are replaced by the corre- + sponding most significant component of the input key's + domain. If the input key is user@mail.example.com, then %1 is com, %2 is example and %3 is mail. If the input key - is unqualified or does not have enough domain components - to satisfy all the specified patterns, the query is sup- + is unqualified or does not have enough domain components + to satisfy all the specified patterns, the query is sup- pressed and returns no results. - The domain parameter described below limits the input keys to - addresses in matching domains. When the domain parameter is + The domain parameter described below limits the input keys to + addresses in matching domains. When the domain parameter is non-empty, SQL queries for unqualified addresses or addresses in non-matching domains are suppressed and return no results. - This parameter is available with Postfix 2.2. In prior releases - the SQL query was built from the separate parameters: - select_field, table, where_field and additional_conditions. The + This parameter is available with Postfix 2.2. In prior releases + the SQL query was built from the separate parameters: + select_field, table, where_field and additional_conditions. The mapping from the old parameters to the equivalent query is: SELECT [select_field] @@ -129,50 +149,50 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) WHERE [where_field] = '%s' [additional_conditions] - The '%s' in the WHERE clause expands to the escaped search - string. With Postfix 2.2 these legacy parameters are used if + The '%s' in the WHERE clause expands to the escaped search + string. With Postfix 2.2 these legacy parameters are used if the query parameter is not specified. NOTE: DO NOT put quotes around the query parameter. result_format (default: %s) Format template applied to result attributes. Most commonly used - to append (or prepend) text to the result. This parameter sup- + to append (or prepend) text to the result. This parameter sup- ports the following '%' expansions: %% This is replaced by a literal '%' character. - %s This is replaced by the value of the result attribute. + %s This is replaced by the value of the result attribute. When result is empty it is skipped. %u When the result attribute value is an address of the form - user@domain, %u is replaced by the local part of the - address. When the result has an empty localpart it is + user@domain, %u is replaced by the local part of the + address. When the result has an empty localpart it is skipped. - %d When a result attribute value is an address of the form - user@domain, %d is replaced by the domain part of the - attribute value. When the result is unqualified it is + %d When a result attribute value is an address of the form + user@domain, %d is replaced by the domain part of the + attribute value. When the result is unqualified it is skipped. %[SUD1-9] - The upper-case and decimal digit expansions interpolate - the parts of the input key rather than the result. Their - behavior is identical to that described with query, and - in fact because the input key is known in advance, - queries whose key does not contain all the information - specified in the result template are suppressed and + The upper-case and decimal digit expansions interpolate + the parts of the input key rather than the result. Their + behavior is identical to that described with query, and + in fact because the input key is known in advance, + queries whose key does not contain all the information + specified in the result template are suppressed and return no results. For example, using "result_format = smtp:[%s]" allows one to use a mailHost attribute as the basis of a transport(5) table. After - applying the result format, multiple values are concatenated as + applying the result format, multiple values are concatenated as comma separated strings. The expansion_limit and parameter - explained below allows one to restrict the number of values in + explained below allows one to restrict the number of values in the result, which is especially useful for maps that must return at most one value. - The default value %s specifies that each result value should be + The default value %s specifies that each result value should be used as is. This parameter is available with Postfix 2.2 and later. @@ -180,15 +200,15 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) NOTE: DO NOT put quotes around the result format! domain (default: no domain list) - This is a list of domain names, paths to files, or "type:table" + This is a list of domain names, paths to files, or "type:table" databases. When specified, only fully qualified search keys with - a *non-empty* localpart and a matching domain are eligible for + a *non-empty* localpart and a matching domain are eligible for lookup: 'user' lookups, bare domain lookups and "@domain" - lookups are not performed. This can significantly reduce the + lookups are not performed. This can significantly reduce the query load on the MySQL server. domain = postfix.org, hash:/etc/postfix/searchdomains - It is best not to use SQL to store the domains eligible for SQL + It is best not to use SQL to store the domains eligible for SQL lookups. This parameter is available with Postfix 2.2 and later. @@ -197,37 +217,37 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) the input keys are always unqualified. expansion_limit (default: 0) - A limit on the total number of result elements returned (as a + A limit on the total number of result elements returned (as a comma separated list) by a lookup against the map. A setting of - zero disables the limit. Lookups fail with a temporary error if - the limit is exceeded. Setting the limit to 1 ensures that + zero disables the limit. Lookups fail with a temporary error if + the limit is exceeded. Setting the limit to 1 ensures that lookups do not return multiple values. option_file - Read options from the given file instead of the default my.cnf - location. This reads options from the [client] option group, + Read options from the given file instead of the default my.cnf + location. This reads options from the [client] option group, optionally followed by options from the group given with option_group. This parameter is available with Postfix 2.11 and later. option_group (default: Postfix >=3.2: client, <= 3.1: empty) - Read options from the given group of the mysql options file, + Read options from the given group of the mysql options file, after reading options from the [client] group. - Postfix 3.2 and later read [client] option group settings by - default. To disable this specify no option_file and specify + Postfix 3.2 and later read [client] option group settings by + default. To disable this specify no option_file and specify "option_group =" (i.e. an empty value). - Postfix 3.1 and earlier don't read [client] option group set- - tings unless a non-empty option_file or option_group value are + Postfix 3.1 and earlier don't read [client] option group set- + tings unless a non-empty option_file or option_group value are specified. To enable this, specify, for example, "option_group = client". This parameter is available with Postfix 2.11 and later. require_result_set (default: yes) - If "yes", require that every query returns a result set. If + If "yes", require that every query returns a result set. If "no", treat the absence of a result set as "not found". This parameter is available with Postfix 3.2 and later. @@ -238,19 +258,19 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) This parameter is available with Postfix 2.11 and later. tls_key_file - File containing the private key corresponding to tls_cert_file. + File containing the private key corresponding to tls_cert_file. This parameter is available with Postfix 2.11 and later. tls_CAfile - File containing certificates for all of the X509 Certification - Authorities the client will recognize. Takes precedence over + File containing certificates for all of the X509 Certification + Authorities the client will recognize. Takes precedence over tls_CApath. This parameter is available with Postfix 2.11 and later. tls_CApath - Directory containing X509 Certification Authority certificates + Directory containing X509 Certification Authority certificates in separate individual files. This parameter is available with Postfix 2.11 and later. @@ -261,13 +281,13 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) This parameter is available with Postfix 2.11 and later. tls_verify_cert (default: no) - Verify that the server's name matches the common name in the + Verify that the server's name matches the common name in the certificate. This parameter is available with Postfix 2.11 and later. USING MYSQL STORED PROCEDURES - Postfix 3.2 and later support calling a stored procedure instead of + Postfix 3.2 and later support calling a stored procedure instead of using a SELECT statement in the query, e.g. query = CALL lookup('%s') @@ -275,17 +295,17 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) The previously described '%' expansions can be used in the parameter(s) to the stored procedure. - By default, every stored procedure call must return a result set, i.e. - every code path must execute a SELECT statement that returns a result + By default, every stored procedure call must return a result set, i.e. + every code path must execute a SELECT statement that returns a result set (instead of storing its results in a table). With - "require_result_set = no", the absence of a result set is treated as + "require_result_set = no", the absence of a result set is treated as "not found". - A stored procedure must not return multiple result sets. That is, - there must be no code path that executes multiple SELECT statements + A stored procedure must not return multiple result sets. That is, + there must be no code path that executes multiple SELECT statements that return a result (instead of storing their results in a table). - The following is an example of a stored procedure returning a single + The following is an example of a stored procedure returning a single result set: CREATE [DEFINER=`user`@`host`] PROCEDURE @@ -297,26 +317,26 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) END OBSOLETE MAIN.CF PARAMETERS - For compatibility with other Postfix lookup tables, MySQL parameters - can also be defined in main.cf. In order to do that, specify as MySQL - source a name that doesn't begin with a slash or a dot. The MySQL - parameters will then be accessible as the name you've given the source - in its definition, an underscore, and the name of the parameter. For - example, if the map is specified as "mysql:mysqlname", the parameter + For compatibility with other Postfix lookup tables, MySQL parameters + can also be defined in main.cf. In order to do that, specify as MySQL + source a name that doesn't begin with a slash or a dot. The MySQL + parameters will then be accessible as the name you've given the source + in its definition, an underscore, and the name of the parameter. For + example, if the map is specified as "mysql:mysqlname", the parameter "hosts" would be defined in main.cf as "mysqlname_hosts". - Note: with this form, the passwords for the MySQL sources are written - in main.cf, which is normally world-readable. Support for this form + Note: with this form, the passwords for the MySQL sources are written + in main.cf, which is normally world-readable. Support for this form will be removed in a future Postfix version. OBSOLETE QUERY INTERFACE - This section describes an interface that is deprecated as of Postfix - 2.2. It is replaced by the more general query interface described - above. If the query parameter is defined, the legacy parameters - described here ignored. Please migrate to the new interface as the + This section describes an interface that is deprecated as of Postfix + 2.2. It is replaced by the more general query interface described + above. If the query parameter is defined, the legacy parameters + described here ignored. Please migrate to the new interface as the legacy interface may be removed in a future release. - The following parameters can be used to fill in a SELECT template + The following parameters can be used to fill in a SELECT template statement of the form: SELECT [select_field] @@ -325,7 +345,7 @@ MYSQL_TABLE(5) MYSQL_TABLE(5) [additional_conditions] The specifier %s is replaced by the search string, and is escaped so if - it contains single quotes or other odd characters, it will not cause a + it contains single quotes or other odd characters, it will not cause a parse error, or worse, a security problem. select_field diff --git a/html/newaliases.1.html b/html/newaliases.1.html index bebc17b..bf6051d 100644 --- a/html/newaliases.1.html +++ b/html/newaliases.1.html @@ -455,9 +455,11 @@ SENDMAIL(1) SENDMAIL(1) The location of the Postfix top-level queue directory. remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and - append the specified domain name to incomplete addresses. + Rewrite or add message headers in mail from remote clients if + the remote_header_rewrite_domain parameter value is non-empty, + updating incomplete addresses with the domain specified in the + remote_header_rewrite_domain parameter, and adding missing head- + ers. syslog_facility (mail) The syslog facility of Postfix logging. diff --git a/html/pcre_table.5.html b/html/pcre_table.5.html index 0216e3e..1e03644 100644 --- a/html/pcre_table.5.html +++ b/html/pcre_table.5.html @@ -191,8 +191,12 @@ PCRE_TABLE(5) PCRE_TABLE(5) Postfix parses the result as if it is a file in /etc/postfix. - Note: if a rule contains $, specify $$ to keep Postfix from trying to - do $name expansion as it evaluates a parameter value. + Note: if an inlined rule contains $, specify $$ to keep Postfix from + trying to do $name expansion as it evaluates a parameter value. + + Note: when using $name inside an inlined pattern, use \Q$name\E to dis- + able metacharacters such as '.' in the $name expansion. Otherwise, the + pattern may have unexpected matches. EXAMPLE SMTPD ACCESS MAP # Protect your outgoing majordomo exploders diff --git a/html/pgsql_table.5.html b/html/pgsql_table.5.html index 964bd6d..0b50fd1 100644 --- a/html/pgsql_table.5.html +++ b/html/pgsql_table.5.html @@ -72,11 +72,24 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) The encoding used by the database client. The default setting is: encoding = UTF8 + Historically, the database client was hard coded to use LATIN1 in an attempt to disable multibyte character support. This feature is available in Postfix 3.8 and later. + idle_interval (default: 60) + The number of seconds after which an idle database connection + will be closed. + + This feature is available in Postfix 3.9 and later. + + retry_interval (default: 60) + The number of seconds that a database connection will be skipped + after an error. + + This feature is available in Postfix 3.9 and later. + query The SQL query template used to search the database, where %s is a substitute for the address Postfix is trying to resolve, e.g. query = SELECT replacement FROM aliases WHERE mailbox = '%s' diff --git a/html/pipe.8.html b/html/pipe.8.html index a0e4678..d813954 100644 --- a/html/pipe.8.html +++ b/html/pipe.8.html @@ -242,13 +242,19 @@ PIPE(8) PIPE(8) This feature is available as of Postfix 2.5. + ${envid} + This macro expands to the RFC 3461 envelope ID if avail- + able, otherwise the empty string. + + This feature is available as of Postfix 3.9. + ${extension} - This macro expands to the extension part of a recipient - address. For example, with an address user+foo@domain + This macro expands to the extension part of a recipient + address. For example, with an address user+foo@domain the extension is foo. - A command-line argument that contains ${extension} - expands into as many command-line arguments as there are + A command-line argument that contains ${extension} + expands into as many command-line arguments as there are recipients. This information is modified by the u flag for case fold- @@ -256,11 +262,11 @@ PIPE(8) PIPE(8) ${mailbox} This macro expands to the complete local part of a recip- - ient address. For example, with an address + ient address. For example, with an address user+foo@domain the mailbox is user+foo. - A command-line argument that contains ${mailbox} expands - to as many command-line arguments as there are recipi- + A command-line argument that contains ${mailbox} expands + to as many command-line arguments as there are recipi- ents. This information is modified by the u flag for case fold- @@ -273,11 +279,11 @@ PIPE(8) PIPE(8) ing. ${original_recipient} - This macro expands to the complete recipient address + This macro expands to the complete recipient address before any address rewriting or aliasing. - A command-line argument that contains ${original_recipi- - ent} expands to as many command-line arguments as there + A command-line argument that contains ${original_recipi- + ent} expands to as many command-line arguments as there are recipients. This information is modified by the hqu flags for quoting @@ -293,8 +299,8 @@ PIPE(8) PIPE(8) ${recipient} This macro expands to the complete recipient address. - A command-line argument that contains ${recipient} - expands to as many command-line arguments as there are + A command-line argument that contains ${recipient} + expands to as many command-line arguments as there are recipients. This information is modified by the hqu flags for quoting @@ -302,13 +308,13 @@ PIPE(8) PIPE(8) ${sasl_method} This macro expands to the name of the SASL authentication - mechanism in the AUTH command when the Postfix SMTP + mechanism in the AUTH command when the Postfix SMTP server received the message. This feature is available as of Postfix 2.2. ${sasl_sender} - This macro expands to the SASL sender name (i.e. the + This macro expands to the SASL sender name (i.e. the original submitter as per RFC 4954) in the MAIL FROM com- mand when the Postfix SMTP server received the message. @@ -321,25 +327,25 @@ PIPE(8) PIPE(8) This feature is available as of Postfix 2.2. ${sender} - This macro expands to the envelope sender address. By - default, the null sender address expands to MAILER-DAE- - MON; this can be changed with the null_sender attribute, + This macro expands to the envelope sender address. By + default, the null sender address expands to MAILER-DAE- + MON; this can be changed with the null_sender attribute, as described above. This information is modified by the q flag for quoting. ${size} This macro expands to Postfix's idea of the message size, - which is an approximation of the size of the message as + which is an approximation of the size of the message as delivered. ${user} - This macro expands to the username part of a recipient - address. For example, with an address user+foo@domain + This macro expands to the username part of a recipient + address. For example, with an address user+foo@domain the username part is user. - A command-line argument that contains ${user} expands - into as many command-line arguments as there are recipi- + A command-line argument that contains ${user} expands + into as many command-line arguments as there are recipi- ents. This information is modified by the u flag for case fold- @@ -349,36 +355,36 @@ PIPE(8) PIPE(8) RFC 3463 (Enhanced status codes) DIAGNOSTICS - Command exit status codes are expected to follow the conventions + Command exit status codes are expected to follow the conventions defined in <sysexits.h>. Exit status 0 means normal successful comple- tion. In the case of a non-zero exit status, a limited amount of command out- - put is logged, and reported in a delivery status notification. When - the output begins with a 4.X.X or 5.X.X enhanced status code, the sta- - tus code takes precedence over the non-zero exit status (Postfix ver- + put is logged, and reported in a delivery status notification. When + the output begins with a 4.X.X or 5.X.X enhanced status code, the sta- + tus code takes precedence over the non-zero exit status (Postfix ver- sion 2.3 and later). - After successful delivery (zero exit status) a limited amount of com- - mand output is logged, and reported in "success" delivery status noti- + After successful delivery (zero exit status) a limited amount of com- + mand output is logged, and reported in "success" delivery status noti- fications (Postfix 3.0 and later). This command output is not examined for the presence of an enhanced status code. - Problems and transactions are logged to syslogd(8) or postlogd(8). - Corrupted message files are marked so that the queue manager can move + Problems and transactions are logged to syslogd(8) or postlogd(8). + Corrupted message files are marked so that the queue manager can move them to the corrupt queue for further inspection. SECURITY - This program needs a dual personality 1) to access the private Postfix - queue and IPC mechanisms, and 2) to execute external commands as the + This program needs a dual personality 1) to access the private Postfix + queue and IPC mechanisms, and 2) to execute external commands as the specified user. It is therefore security sensitive. CONFIGURATION PARAMETERS Changes to main.cf are picked up automatically as pipe(8) processes run - for only a limited amount of time. Use the command "postfix reload" to + for only a limited amount of time. Use the command "postfix reload" to speed up a change. - The text below provides only a parameter summary. See postconf(5) for + The text below provides only a parameter summary. See postconf(5) for more details including examples. RESOURCE AND RATE CONTROLS @@ -386,50 +392,50 @@ PIPE(8) PIPE(8) transport_time_limit ($command_time_limit) A transport-specific override for the command_time_limit parame- - ter value, where transport is the master.cf name of the message + ter value, where transport is the master.cf name of the message delivery transport. Implemented in the qmgr(8) daemon: transport_destination_concurrency_limit ($default_destination_concur- rency_limit) - A transport-specific override for the default_destination_con- + A transport-specific override for the default_destination_con- currency_limit parameter value, where transport is the master.cf name of the message delivery transport. transport_destination_recipient_limit ($default_destination_recipi- ent_limit) A transport-specific override for the default_destination_recip- - ient_limit parameter value, where transport is the master.cf + ient_limit parameter value, where transport is the master.cf name of the message delivery transport. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to handle a + How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log- ging sub-second delay values. export_environment (see 'postconf -d' output) - The list of environment variables that a Postfix process will + The list of environment variables that a Postfix process will export to non-Postfix processes. ipc_timeout (3600s) - The time limit for sending or receiving information over an + The time limit for sending or receiving information over an internal communication channel. mail_owner (postfix) - The UNIX system account that owns the Postfix queue and most + The UNIX system account that owns the Postfix queue and most Postfix daemon processes. max_idle (100s) - The maximum amount of time that an idle Postfix daemon process + The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. max_use (100) @@ -446,28 +452,28 @@ PIPE(8) PIPE(8) The location of the Postfix top-level queue directory. recipient_delimiter (empty) - The set of characters that can separate an email address local- + The set of characters that can separate an email address local- part, user name, or a .forward file name from its extension. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix version 3.0 and later: pipe_delivery_status_filter ($default_delivery_status_filter) - Optional filter for the pipe(8) delivery agent to change the + Optional filter for the pipe(8) delivery agent to change the delivery status code or explanatory text of successful or unsuc- cessful deliveries. Available in Postfix version 3.3 and later: enable_original_recipient (yes) - Enable support for the original recipient address after an - address is rewritten to a different address (for example with + Enable support for the original recipient address after an + address is rewritten to a different address (for example with aliasing or with canonical mapping). service_name (read-only) @@ -476,7 +482,7 @@ PIPE(8) PIPE(8) Available in Postfix 3.5 and later: info_log_address_format (external) - The email address form that will be used in non-debug logging + The email address form that will be used in non-debug logging (info, warning, etc.). SEE ALSO diff --git a/html/postcat.1.html b/html/postcat.1.html index 4c61c52..71b763e 100644 --- a/html/postcat.1.html +++ b/html/postcat.1.html @@ -85,7 +85,7 @@ POSTCAT(1) POSTCAT(1) figuration files. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix + The list of environment variables that a privileged Postfix process will import from a non-Postfix parent process, or name=value environment overrides. diff --git a/html/postconf.1.html b/html/postconf.1.html index 4269a5e..a8444a2 100644 --- a/html/postconf.1.html +++ b/html/postconf.1.html @@ -13,7 +13,7 @@ POSTCONF(1) POSTCONF(1) SYNOPSIS Managing main.cf: - postconf [-dfhHnopvx] [-c config_dir] [-C class,...] [parameter ...] + postconf [-dfhHnopqvx] [-c config_dir] [-C class,...] [parameter ...] postconf [-epv] [-c config_dir] parameter=value ... @@ -23,7 +23,7 @@ POSTCONF(1) POSTCONF(1) Managing master.cf service entries: - postconf -M [-fovx] [-c config_dir] [service[/type] ...] + postconf -M [-foqvx] [-c config_dir] [service[/type] ...] postconf -M [-ev] [-c config_dir] service/type=value ... @@ -33,13 +33,13 @@ POSTCONF(1) POSTCONF(1) Managing master.cf service fields: - postconf -F [-fhHovx] [-c config_dir] [service[/type[/field]] ...] + postconf -F [-fhHoqvx] [-c config_dir] [service[/type[/field]] ...] postconf -F [-ev] [-c config_dir] service/type/field=value ... Managing master.cf service parameters: - postconf -P [-fhHovx] [-c config_dir] [service[/type[/parameter]] ...] + postconf -P [-fhHoqvx] [-c config_dir] [service[/type[/parameter]] ...] postconf -P [-ev] [-c config_dir] service/type/parameter=value ... @@ -272,52 +272,58 @@ POSTCONF(1) POSTCONF(1) This feature is available with Postfix 2.9 and later. + mongodb + MongoDB database client. This is described in mongodb_ta- + ble(5). + + This feature is available with Postfix 3.9 and later. + mysql (read-only) MySQL database client. Available on systems with support - for MySQL databases. This is described in mysql_ta- + for MySQL databases. This is described in mysql_ta- ble(5). pcre (read-only) - A lookup table based on Perl Compatible Regular Expres- + A lookup table based on Perl Compatible Regular Expres- sions. The file format is described in pcre_table(5). pgsql (read-only) - PostgreSQL database client. This is described in + PostgreSQL database client. This is described in pgsql_table(5). This feature is available with Postfix 2.1 and later. pipemap (read-only) - A lookup table that constructs a pipeline of tables. - Example: "pipemap:{type_1:name_1, ..., type_n:name_n}". - Each "pipemap:" query is given to the first table. Each + A lookup table that constructs a pipeline of tables. + Example: "pipemap:{type_1:name_1, ..., type_n:name_n}". + Each "pipemap:" query is given to the first table. Each lookup result becomes the query for the next table in the - pipeline, and the last table produces the final result. - When any table lookup produces no result, the pipeline - produces no result. The first and last characters of the + pipeline, and the last table produces the final result. + When any table lookup produces no result, the pipeline + produces no result. The first and last characters of the "pipemap:" table name must be "{" and "}". Within these, individual maps are separated with comma or whitespace. This feature is available with Postfix 3.0 and later. - proxy Postfix proxymap(8) client for shared access to Postfix + proxy Postfix proxymap(8) client for shared access to Postfix databases. The table name syntax is type:name. This feature is available with Postfix 2.0 and later. randmap (read-only) - An in-memory table that performs random selection. Exam- + An in-memory table that performs random selection. Exam- ple: "randmap:{result_1, ..., result_n}". Each table query returns a random choice from the specified results. - The first and last characters of the "randmap:" table - name must be "{" and "}". Within these, individual + The first and last characters of the "randmap:" table + name must be "{" and "}". Within these, individual results are separated with comma or whitespace. To give a specific result more weight, specify it multiple times. This feature is available with Postfix 3.0 and later. regexp (read-only) - A lookup table based on regular expressions. The file + A lookup table based on regular expressions. The file format is described in regexp_table(5). sdbm An indexed file type based on hashing. Available on sys- @@ -326,9 +332,9 @@ POSTCONF(1) POSTCONF(1) This feature is available with Postfix 2.2 and later. socketmap (read-only) - Sendmail-style socketmap client. The table name is - inet:host:port:name for a TCP/IP server, or unix:path- - name:name for a UNIX-domain server. This is described in + Sendmail-style socketmap client. The table name is + inet:host:port:name for a TCP/IP server, or unix:path- + name:name for a UNIX-domain server. This is described in socketmap_table(5). This feature is available with Postfix 2.10 and later. @@ -339,11 +345,11 @@ POSTCONF(1) POSTCONF(1) This feature is available with Postfix 2.8 and later. static (read-only) - A table that always returns its name as lookup result. + A table that always returns its name as lookup result. For example, static:foobar always returns the string foo- - bar as lookup result. Specify "static:{ text with white- - space }" when the result contains whitespace; this form - ignores whitespace after the opening "{" and before the + bar as lookup result. Specify "static:{ text with white- + space }" when the result contains whitespace; this form + ignores whitespace after the opening "{" and before the closing "}". See also the inline: map. The form "static:{text} is available with Postfix 3.0 and @@ -353,66 +359,66 @@ POSTCONF(1) POSTCONF(1) TCP/IP client. The protocol is described in tcp_table(5). texthash (read-only) - Produces similar results as hash: files, except that you - don't need to run the postmap(1) command before you can - use the file, and that it does not detect changes after + Produces similar results as hash: files, except that you + don't need to run the postmap(1) command before you can + use the file, and that it does not detect changes after the file is read. This feature is available with Postfix 2.8 and later. unionmap (read-only) - A table that sends each query to multiple lookup tables - and that concatenates all found results, separated by + A table that sends each query to multiple lookup tables + and that concatenates all found results, separated by comma. The table name syntax is the same as for pipemap. This feature is available with Postfix 3.0 and later. unix (read-only) - A limited view of the UNIX authentication database. The + A limited view of the UNIX authentication database. The following tables are implemented: unix:passwd.byname - The table is the UNIX password database. The key - is a login name. The result is a password file + The table is the UNIX password database. The key + is a login name. The result is a password file entry in passwd(5) format. unix:group.byname The table is the UNIX group database. The key is a - group name. The result is a group file entry in + group name. The result is a group file entry in group(5) format. - Other table types may exist depending on how Postfix was built. + Other table types may exist depending on how Postfix was built. - -M Show master.cf file contents instead of main.cf file contents. + -M Show master.cf file contents instead of main.cf file contents. Specify -Mf to fold long lines for human readability. Specify zero or more arguments, each with a service-name or ser- - vice-name/service-type pair, where service-name is the first - field of a master.cf entry and service-type is one of (inet, + vice-name/service-type pair, where service-name is the first + field of a master.cf entry and service-type is one of (inet, unix, fifo, or pass). - If service-name or service-name/service-type is specified, only - the matching master.cf entries will be output. For example, - "postconf -Mf smtp" will output all services named "smtp", and - "postconf -Mf smtp/inet" will output only the smtp service that - listens on the network. Trailing service type fields that are + If service-name or service-name/service-type is specified, only + the matching master.cf entries will be output. For example, + "postconf -Mf smtp" will output all services named "smtp", and + "postconf -Mf smtp/inet" will output only the smtp service that + listens on the network. Trailing service type fields that are omitted will be handled as "*" wildcard fields. This feature is available with Postfix 2.9 and later. The syntax - was changed from "name.type" to "name/type", and "*" wildcard + was changed from "name.type" to "name/type", and "*" wildcard support was added with Postfix 2.11. -n Show only configuration parameters that have explicit name=value - settings in main.cf. Specify -nf to fold long lines for human - readability (Postfix 2.9 and later). To show settings that dif- + settings in main.cf. Specify -nf to fold long lines for human + readability (Postfix 2.9 and later). To show settings that dif- fer from built-in defaults only, use the following bash syntax: LANG=C comm -23 <(postconf -n) <(postconf -d) Replace "-23" with "-12" to show settings that duplicate built-in defaults. -o name=value - Override main.cf parameter settings. This lets you see the - effect changing a parameter would have when it is used in other + Override main.cf parameter settings. This lets you see the + effect changing a parameter would have when it is used in other configuration parameters, e.g.: postconf -x -o stress=yes @@ -422,38 +428,42 @@ POSTCONF(1) POSTCONF(1) This feature is available with Postfix 2.11 and later. - -P Show master.cf service parameter settings (by default all ser- - vices and all parameters), formatted as "service/type/parame- + -P Show master.cf service parameter settings (by default all ser- + vices and all parameters), formatted as "service/type/parame- ter=value", one per line. Specify -Pf to fold long lines. - Specify one or more "service/type/parameter" instances on the - postconf(1) command line to limit the output to parameters of - interest. Trailing parameter name or service type fields that + Specify one or more "service/type/parameter" instances on the + postconf(1) command line to limit the output to parameters of + interest. Trailing parameter name or service type fields that are omitted will be handled as "*" wildcard fields. This feature is available with Postfix 2.11 and later. + -q Do not log warnings for deprecated or unused parameters. + + This feature is available with Postfix 3.9 and later. + -t [template_file] - Display the templates for text that appears at the beginning of - delivery status notification (DSN) messages, without expanding + Display the templates for text that appears at the beginning of + delivery status notification (DSN) messages, without expanding $name expressions. - To override the bounce_template_file parameter setting, specify - a template file name at the end of the "postconf -t" command - line. Specify an empty file name to display built-in templates + To override the bounce_template_file parameter setting, specify + a template file name at the end of the "postconf -t" command + line. Specify an empty file name to display built-in templates (in shell language: ""). This feature is available with Postfix 2.3 and later. -T mode - If Postfix is compiled without TLS support, the -T option pro- - duces no output. Otherwise, if an invalid mode is specified, - the -T option reports an error and exits with a non-zero status + If Postfix is compiled without TLS support, the -T option pro- + duces no output. Otherwise, if an invalid mode is specified, + the -T option reports an error and exits with a non-zero status code. The valid modes are: compile-version Output the OpenSSL version that Postfix was compiled with - (i.e. the OpenSSL version in a header file). The output + (i.e. the OpenSSL version in a header file). The output format is the same as with the command "openssl version". run-version @@ -461,40 +471,40 @@ POSTCONF(1) POSTCONF(1) runtime (i.e. the OpenSSL version in a shared library). public-key-algorithms - Output the lower-case names of the supported public-key + Output the lower-case names of the supported public-key algorithms, one per-line. This feature is available with Postfix 3.1 and later. - -v Enable verbose logging for debugging purposes. Multiple -v + -v Enable verbose logging for debugging purposes. Multiple -v options make the software increasingly verbose. - -x Expand $name in main.cf or master.cf parameter values. The + -x Expand $name in main.cf or master.cf parameter values. The expansion is recursive. This feature is available with Postfix 2.10 and later. - -X Edit the main.cf configuration file, and remove the parameters + -X Edit the main.cf configuration file, and remove the parameters named on the postconf(1) command line. Specify a list of param- eter names, not "name=value" pairs. - With -M, edit the master.cf configuration file, and remove one - or more service entries as specified with "service/type" on the + With -M, edit the master.cf configuration file, and remove one + or more service entries as specified with "service/type" on the postconf(1) command line. - With -P, edit the master.cf configuration file, and remove one + With -P, edit the master.cf configuration file, and remove one or more service parameter settings (-o parameter=value settings) - as specified with "service/type/parameter" on the postconf(1) + as specified with "service/type/parameter" on the postconf(1) command line. In all cases the file is copied to a temporary file then renamed into place. Specify quotes to protect special characters on the postconf(1) command line. - There is no postconf(1) command to perform the reverse opera- + There is no postconf(1) command to perform the reverse opera- tion. - This feature is available with Postfix 2.10 and later. Support + This feature is available with Postfix 2.10 and later. Support for -M and -P was added with Postfix 2.11. -# Edit the main.cf configuration file, and comment out the parame- @@ -502,18 +512,18 @@ POSTCONF(1) POSTCONF(1) eters revert to their default values. Specify a list of parame- ter names, not "name=value" pairs. - With -M, edit the master.cf configuration file, and comment out - one or more service entries as specified with "service/type" on + With -M, edit the master.cf configuration file, and comment out + one or more service entries as specified with "service/type" on the postconf(1) command line. In all cases the file is copied to a temporary file then renamed into place. Specify quotes to protect special characters on the postconf(1) command line. - There is no postconf(1) command to perform the reverse opera- + There is no postconf(1) command to perform the reverse opera- tion. - This feature is available with Postfix 2.6 and later. Support + This feature is available with Postfix 2.6 and later. Support for -M was added with Postfix 2.11. DIAGNOSTICS @@ -524,18 +534,18 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant to this pro- + The following main.cf parameters are especially relevant to this pro- gram. - The text below provides only a parameter summary. See postconf(5) for + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. bounce_template_file (empty) - Pathname of a configuration file with bounce message templates. + Pathname of a configuration file with bounce message templates. FILES /etc/postfix/main.cf, Postfix configuration parameters diff --git a/html/postconf.5.html b/html/postconf.5.html index dbb8cc8..0ac9b68 100644 --- a/html/postconf.5.html +++ b/html/postconf.5.html @@ -612,8 +612,14 @@ Examples: (default: see "postconf -d" output)

      -The alias databases that are used for local(8) delivery. See -aliases(5) for syntax details. +Optional lookup tables with aliases that apply only to local(8) +recipients; this is unlike virtual_alias_maps that apply to all +recipients: local(8), virtual, and remote. +The table format and lookups are documented in aliases(5). For an +overview of Postfix address manipulations see the ADDRESS_REWRITING_README +document.

      + +

      Specify zero or more "type:name" lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. @@ -2732,19 +2738,30 @@ name of the message delivery transport.

      The default mail delivery transport and next-hop destination for -destinations that do not match $mydestination, $inet_interfaces, +the default domain class: recipient domains that do not match +$mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, -or $relay_domains. This information can be overruled with the -sender_dependent_default_transport_maps parameter and with the -transport(5) table.

      +or $relay_domains. This information will not be used when +sender_dependent_default_transport_maps returns a result, and may +be overridden with the transport(5) table.

      -

      -In order of decreasing precedence, the nexthop destination is taken -from $sender_dependent_default_transport_maps, $default_transport, -$sender_dependent_relayhost_maps, $relayhost, or from the recipient -domain. +

      For recipient domains in the default domain class:

      + +

      +

      Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. @@ -3713,6 +3730,25 @@ This feature is available in Postfix 2.0 and later.

      +
      + +
      force_mime_input_conversion +(default: no)
      + +

      Convert body content that claims to be 8-bit into quoted-printable, +before header_checks, body_checks, Milters, and before after-queue +content filters. This feature does not affect messages that are +sent into smtpd_proxy_filter.

      + +

      The typical use case is an MTA that applies this conversion +before signing outbound messages, so that the signatures will remain +valid when a message is later delivered to an MTA that does not +announce 8BITMIME support, or when a message line exceeds the SMTP +length limit.

      + +

      This feature is available in Postfix ≥ 3.9.

      + +
      fork_attempts @@ -3797,7 +3833,7 @@ filtered with the character set that is specified with the
      The address extension delimiter that was found in the recipient address (Postfix 2.11 and later), or the 'first' delimiter specified with the system-wide recipient address extension delimiter (Postfix -3.5.22, 3.5.12, 3.7.8, 3.8.3 and later). Historically, this was +3.5.22, 3.6.12, 3.7.8, 3.8.3 and later). Historically, this was always the system-wide recipient address extension delimiter (Postfix 2.10 and earlier).
      @@ -4154,12 +4190,17 @@ Specify 0 to disable the feature. Valid delays are 0..10.
      inet_interfaces (default: all)
      -

      The local network interface addresses that this mail system receives -mail on. Specify "all" to receive mail on all network -interfaces (default), and "loopback-only" to receive mail -on loopback network interfaces only (Postfix version 2.2 and later). The -parameter also controls delivery of mail to user@[ip.address]. -

      +

      The local network interface addresses that this mail system +receives mail on. Specify "all" to receive mail on all network +interfaces (default), "loopback-only" to receive mail on loopback +network interfaces only (Postfix version 2.2 and later), or zero +or more IPv4 or IPv6 addresses (IPv6 is supported in Postfix version +2.2 and later). The parameter also controls whether Postfix will +accept mail for user@[ip.address], and prevents Postfix +from delivering mail to a host that has equal or larger MX preference. +Specify an empty value if Postfix does not receive mail over the +network, or if all network listeners have an explicit IP address +in master.cf.

      Note 1: you need to stop and start Postfix when this parameter changes. @@ -4168,22 +4209,44 @@ Note 1: you need to stop and start Postfix when this parameter changes.

      Note 2: address information may be enclosed inside [], but this form is not required here.

      -

      When inet_interfaces specifies just one IPv4 and/or IPv6 address -that is not a loopback address, the Postfix SMTP client will use -this address as the IP source address for outbound mail. Support -for IPv6 is available in Postfix version 2.2 and later.

      +

      When smtp_bind_address and/or smtp_bind_address6 are not +specified, the inet_interfaces setting may constrain the source IP +address for an outbound SMTP or LMTP connection as described below. +

      + +

      The following text is specific to SMTP and IPv4. The same +reasoning applies to the IPv6 protocol, and to the Postfix LMTP +client. To disable IPv4 or IPv6 support in the Postfix SMTP and +LMTP client, use inet_protocols.

      -

      -On a multi-homed firewall with separate Postfix instances listening on the -"inside" and "outside" interfaces, this can prevent each instance from -being able to reach remote SMTP servers on the "other side" of the -firewall. Setting -smtp_bind_address to 0.0.0.0 avoids the potential problem for -IPv4, and setting smtp_bind_address6 to :: solves the problem -for IPv6.

      +
        + +
      • When inet_interfaces specifies one IPv4 address, and that +is not a loopback address, the Postfix SMTP client uses that as the +source address for outbound IPv4 connections.

        + +
      • Otherwise, the Postfix SMTP client does not constrain the +source IPv4 address, and connects using a system-chosen source IPv4 +address. This includes the cases where inet_interfaces is empty, +where it specifies all, or where it contains no IPv4 address, +one IPv4 address that is a loopback address, or multiple IPv4 +addresses.

        + +
      + +

      A Postfix SMTP client may fail to reach some remote SMTP servers +when the client source IP address is constrained explicitly with +smtp_bind_address or smtp_bind_address6, or implicitly with +inet_interfaces. This can happen when Postfix runs on a multi-homed +system such as a firewall, the Postfix SMTP source client IP address +is constrained to one specific network interface, and the remote +SMTP server must be reached through a different interface. Setting +smtp_bind_address to 0.0.0.0 avoids the potential problem for IPv4, +and setting smtp_bind_address6 to :: solves the problem for IPv6. +

      -A better solution for multi-homed firewalls is to leave inet_interfaces +A better solution for multi-homed systems is to leave inet_interfaces at the default value and instead use explicit IP addresses in the master.cf SMTP server definitions. This preserves the Postfix SMTP client's @@ -4215,7 +4278,7 @@ Examples:

      inet_protocols -(default: see 'postconf -d output')
      +(default: see 'postconf -d' output)

      The Internet protocols Postfix will attempt to use when making or accepting connections. Specify one or more of "ipv4" @@ -4893,6 +4956,9 @@ configuration parameter. See there for details.

      The LMTP-specific version of the smtp_enforce_tls configuration parameter. See there for details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_security_level instead.

      +

      This feature is available in Postfix 2.3 and later.

      @@ -5293,6 +5359,15 @@ to the remote host.

      +
      + +
      lmtp_sasl_password_result_delimiter +(default: :)
      + +

      The LMTP-specific version of the smtp_sasl_password_result_delimiter +configuration parameter. See there for details.

      + +
      lmtp_sasl_path @@ -5592,6 +5667,17 @@ parameter. See there for details.

      compiled and linked with OpenSSL 1.0.0 or later.

      + + +
      lmtp_tls_enable_rpk +(default: yes)
      + +

      The LMTP-specific version of the smtp_tls_enable_rpk +configuration parameter. See there for details.

      + +

      This feature is available in Postfix 3.9 and later.

      + +
      lmtp_tls_enforce_peername @@ -5694,7 +5780,7 @@ configuration parameter. See there for details.

      lmtp_tls_mandatory_protocols -(default: see postconf -d output)
      +(default: see 'postconf -d' output)

      The LMTP-specific version of the smtp_tls_mandatory_protocols configuration parameter. See there for details.

      @@ -5721,6 +5807,9 @@ configuration parameter. See there for details.

      The LMTP-specific version of the smtp_tls_per_site configuration parameter. See there for details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_policy_maps instead.

      +

      This feature is available in Postfix 2.3 and later.

      @@ -5738,7 +5827,7 @@ configuration parameter. See there for details.

      lmtp_tls_protocols -(default: see postconf -d output)
      +(default: see 'postconf -d' output)

      The LMTP-specific version of the smtp_tls_protocols configuration parameter. See there for details.

      @@ -5853,6 +5942,9 @@ parameter. See there for details.

      The LMTP-specific version of the smtp_use_tls configuration parameter. See there for details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_security_level instead.

      +

      This feature is available in Postfix 2.3 and later.

      @@ -6149,8 +6241,8 @@ until a match is found.

      If this parameter is non-empty (the default), then the Postfix SMTP -server will reject mail for unknown local users. -

      +server will reject mail for unknown local users. Other Postfix +interfaces may still accept an "unknown" recipient.

      To turn off local recipient checking in the Postfix SMTP server, @@ -6449,6 +6541,11 @@ and later.

      The domain part of the recipient address.
      +
      ENVID
      + +
      The optional RFC 3461 envelope ID. Available in Postfix version +3.9 and later
      +
      EXTENSION
      The optional address extension.
      @@ -6681,6 +6778,21 @@ first argument.

      This feature is available in Postfix 3.4 and later.

      + + +
      maillog_file_permissions +(default: 0600)
      + +

      The file access permissions that will be set when the file +$maillog_file is created for the first time, or when the file is +created after an existing file is rotated. Specify one of: 0600 +(only super-user read/write access), 0640 (adds 'group' read +access), or 0644 (also adds 'other' read access). The leading +'0' is optional.

      + +

      This feature is available in Postfix 3.9 and later.

      + +
      maillog_file_prefixes @@ -8326,9 +8438,9 @@ it passes the test, before it can talk to a real Postfix SMTP server.
      postscreen_bare_newline_ttl (default: 30d)
      -

      The amount of time that postscreen(8) will use the result from -a successful "bare newline" SMTP protocol test. During this -time, the client IP address is excluded from this test. The default +

      The amount of time that postscreen(8) remembers that a client +IP address passed a "bare newline" SMTP protocol test, before it +address is required to pass that test again. The default is long because a remote SMTP client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server.

      @@ -8584,9 +8696,10 @@ defined with the postscreen_dns

      Specify a negative value to enable this feature. When a client passes the postscreen_dnsbl_allowlist_threshold without having failed other tests, all pending or disabled tests are flagged as -completed with a time-to-live value equal to postscreen_dnsbl_ttl. -When a test was already completed, its time-to-live value is updated -if it was less than postscreen_dnsbl_ttl.

      +completed with an expiration time based on the DNS reply TTL. +When a test was already completed, its expiration time is updated +if it was less than the value based on the DNS reply TTL. See +also postscreen_dnsbl_max_ttl and postscreen_dnsbl_min_ttl.

      This feature is available in Postfix 3.6 and later.

      @@ -8599,9 +8712,9 @@ if it was less than postscreen_dn
      postscreen_dnsbl_max_ttl (default: ${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)
      -

      The maximum amount of time that postscreen(8) will use the -result from a successful DNS-based reputation test before a -client IP address is required to pass that test again. If the DNS +

      The maximum amount of time that postscreen(8) remembers that a +client IP address passed a DNS-based reputation test, before it is +required to pass that test again. If the DNS reply specifies a shorter TTL value, that value will be used unless it would be smaller than postscreen_dnsbl_min_ttl.

      @@ -8619,9 +8732,9 @@ is backwards-compatible with older Postfix versions.

      postscreen_dnsbl_min_ttl (default: 60s)
      -

      The minimum amount of time that postscreen(8) will use the -result from a successful DNS-based reputation test before a -client IP address is required to pass that test again. If the DNS +

      The minimum amount of time that postscreen(8) remembers that a +client IP address passed a DNS-based reputation test, before it +is required to pass that test again. If the DNS reply specifies a larger TTL value, that value will be used unless it would be larger than postscreen_dnsbl_max_ttl.

      @@ -8762,9 +8875,9 @@ The default time unit is s (seconds).

      postscreen_dnsbl_ttl (default: 1h)
      -

      The amount of time that postscreen(8) will use the result from -a successful DNS-based reputation test before a client -IP address is required to pass that test again.

      +

      The amount of time that postscreen(8) remembers that a client +IP address passed a DNS-based reputation test, before it is required +to pass that test again.

      Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s @@ -8880,9 +8993,9 @@ value to disable this feature.

      postscreen_greet_ttl (default: 1d)
      -

      The amount of time that postscreen(8) will use the result from -a successful PREGREET test. During this time, the client IP address -is excluded from this test. The default is relatively short, because +

      The amount of time that postscreen(8) remembers that a client +IP address passed a PREGREET test, before it is required to pass +that test again. The default is relatively short, because a good client can immediately talk to a real Postfix SMTP server.

      Specify a non-zero time value (an integral value plus an optional @@ -8976,9 +9089,9 @@ test, before it can talk to a real Postfix SMTP server.

      postscreen_non_smtp_command_ttl (default: 30d)
      -

      The amount of time that postscreen(8) will use the result from -a successful "non_smtp_command" SMTP protocol test. During this -time, the client IP address is excluded from this test. The default +

      The amount of time that postscreen(8) remembers that a client +IP address passed a "non_smtp_command" SMTP protocol test, before +it is required to pass that test again. The default is long because a client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server.

      @@ -9044,9 +9157,9 @@ server.

      postscreen_pipelining_ttl (default: 30d)
      -

      The amount of time that postscreen(8) will use the result from -a successful "pipelining" SMTP protocol test. During this time, the -client IP address is excluded from this test. The default is +

      The amount of time that postscreen(8) remembers that a client +IP address passed a "pipelining" SMTP protocol test, before it is +required to pass that test again. The default is long because a good client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server.

      @@ -10136,13 +10249,24 @@ This feature is available in Postfix 2.0 and later.

      The default mail delivery transport and next-hop destination for -remote delivery to domains listed with $relay_domains. In order of -decreasing precedence, the nexthop destination is taken from -$relay_transport, $sender_dependent_relayhost_maps, $relayhost, or -from the recipient domain. This information can be overruled with -the transport(5) table. +the relay domain address class: recipient domains that match +$relay_domains.

      + +

      For recipient domains in the relay domain address class:

      + + +

      Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. @@ -10166,13 +10290,31 @@ This feature is available in Postfix 2.0 and later. (default: empty)

      -The next-hop destination(s) for non-local mail; overrides non-local -domains in recipient addresses. This information is overruled with -relay_transport, sender_dependent_default_transport_maps, -default_transport, sender_dependent_relayhost_maps -and with the transport(5) table. +The next-hop destination(s) for non-local mail; takes precedence +over non-local domains in recipient addresses. This information +will not be used when the sender matches $sender_dependent_relayhost_maps.

      +

      In order of decreasing precedence:

      + + +

      On an intranet, specify the organizational domain name. If your internal DNS uses no MX records, specify the name of the intranet @@ -10180,11 +10322,12 @@ gateway host instead.

      -In the case of SMTP or LMTP delivery, specify one or more destinations -in the form of a domain name, hostname, hostname:port, [hostname]:port, -[hostaddress] or [hostaddress]:port, separated by comma or whitespace. -The form [hostname] turns off MX lookups. Multiple destinations are -supported in Postfix 3.5 and later. +In the case of SMTP delivery, specify one or more destinations in +the form of a domain name, hostname, hostname:service, [hostname]:service, +[hostaddress] or [hostaddress]:service, separated by comma or whitespace. +The form [hostname] turns off MX or SRV lookups. Multiple destinations +are supported in Postfix 3.5 and later. Each destination is tried +in the specified order.

      @@ -10589,18 +10732,38 @@ address and @domain. A lookup result of DUNNO terminates the search without overriding the global default_transport parameter setting. This information is overruled with the transport(5) table.

      -

      -Specify zero or more "type:name" lookup tables, separated by -whitespace or comma. Tables will be searched in the specified order -until a match is found. +

      This setting affects only the default domain address class +(recipient domains that do not match $mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +or $relay_domains):

      + + +

      Note: this overrides default_transport, not transport_maps, and therefore the expected syntax is that of default_transport, not the syntax of transport_maps. Specifically, this does not support the transport_maps syntax for null transport, null nexthop, or null email addresses.

      +

      +Specify zero or more "type:name" lookup tables, separated by +whitespace or comma. Tables will be searched in the specified order +until a match is found. +

      +

      For safety reasons, this feature does not allow $number substitutions in regular expression maps.

      @@ -10616,9 +10779,27 @@ substitutions in regular expression maps.

      setting. The tables are searched by the envelope sender address and @domain. A lookup result of DUNNO terminates the search without overriding the global relayhost parameter setting (Postfix 2.6 and -later). This information is overruled with relay_transport, -sender_dependent_default_transport_maps, default_transport and with -the transport(5) table.

      +later).

      + +

      In order of decreasing precedence:

      + +

      Specify zero or more "type:name" lookup tables, separated by @@ -10820,13 +11001,38 @@ IPv6 connectivity:

      • The setting "smtp_address_preference = ipv6" is unsafe. -It can fail to deliver mail when there is an outage that affects -IPv6, while the destination is still reachable over IPv4.

        +All deliveries will suffer delays during an IPv6 outage, even +while the destination is still reachable over IPv4. Mail may be +stuck in the queue with Postfix versions < 3.3 that do not +implement "smtp_balance_inet_protocols". For similar reasons, the +setting "smtp_address_preference = ipv4" is also unsafe.

      • The setting "smtp_address_preference = any" is safe. With -this, mail will eventually be delivered even if there is an outage +this, and "smtp_balance_inet_protocols = yes" (the default), only +half of deliveries will suffer delays if there is an outage that affects IPv6 or IPv4, as long as it does not affect both.

        +
      • The setting "smtp_address_preference = ipv4" is not a +solution for remote servers that flag email received over IPv6 as +more 'spammy' (the client IPv6 address has a bad or missing PTR or +AAAA record, bad network neighbors, etc.). Instead, configure Postfix +to receive mail over both IPv4 and IPv6, and to deliver mail over +only IPv4.

        + +
        +
        +/etc/postfix/main.cf:
        +    inet_protocols = all
        +
        +
        + +
        +
        +/etc/postfix/master.cf
        +    smtp ...other fields... smtp -o inet_protocols=ipv4
        +
        +
        +

      This feature is available in Postfix 2.8 and later.

      @@ -12295,6 +12501,9 @@ If no username:password entry is found, then the Postfix SMTP client will not attempt to authenticate to the remote host.

      +

      Use smtp_sasl_password_result_delimiter to specify an +alternative separator between username and password.

      +

      The Postfix SMTP client opens the lookup table before going to chroot jail, so you can leave the password file in /etc/postfix. @@ -12307,6 +12516,18 @@ until a match is found.

      +
      + +
      smtp_sasl_password_result_delimiter +(default: :)
      + +

      The delimiter between username and password in sasl_passwd_maps lookup +results. Specify one non-whitespace character that does not appear in +the username.

      + +

      This feature is available in Postfix ≥ 3.9.

      + +
      smtp_sasl_path @@ -13033,6 +13254,86 @@ to anyone else.

      compiled and linked with OpenSSL 1.0.0 or later.

      + + +
      smtp_tls_enable_rpk +(default: no)
      + +

      Request that remote SMTP servers send an RFC7250 raw public key +instead of an X.509 certificate. This feature and the enable_rpk +policy attribute are ignored when there is no raw public key support +in the local TLS implementation.

      + +
        + +
      • At the "may", "encrypt" and "fingerprint" security levels, +with parameter setting "smtp_tls_enable_rpk = yes" or with "enable_rpk += yes" in a policy entry, the Postfix SMTP client will indicate in +the TLS handshake that it prefers to receive a raw server public +key, but it will still accept a server public key certificate.

        + +
      • At the "fingerprint" security level, with parameter setting +"smtp_tls_enable_rpk = yes" or with "enable_rpk = yes" in a policy +entry, server authentication based on certificate fingerprints +becomes more fragile. Even if the server private key and certificate +remain unchanged, the remote SMTP server will fail fingerprint +authentication (won't match the configured list of fingerprints) +when it starts sending a raw public key instead of a certificate, +after its TLS implementation is updated with raw public key support. +Therefore, DO NOT enable raw public keys to remote destinations +authenticated by server certificate fingerprints. You should +enable raw public keys only for servers matched via their public +key fingerprint.

        + +
      • At the "verify" and "secure" security levels, the Postfix +SMTP client always ignores the parameter setting smtp_tls_enable_rpk +or the enable_rpk policy attribute.

        + +
      • At the opportunistic "dane" security level, the Postfix +SMTP client ignores the parameter setting smtp_tls_enable_rpk or +the enable_rpk policy attribute (but it will respect them when it +falls back to the "may" or "encrypt" level). When all valid TLSA +records specify only server public keys (no certificates) and the +local TLS implementation supports raw public keys, the client will +indicate in the TLS handshake that it prefers to receive a raw +public key, but it will still accept a public key certificate.

        + +
      • At the mandatory "dane-only" security level, the Postfix +SMTP client always ignores the parameter setting smtp_tls_enable_rpk +or the enable_rpk policy attribute. When all valid TLSA records +specify only server public keys (no certificates) and the local TLS +implementation supports raw public keys, the client will indicate +in the TLS handshake that it prefers to receive a raw public key, +but it will still accept a public key certificate.

        + +
      + +

      The Postfix SMTP client is always willing to send raw public keys +to servers that solicit them when a client certificate is configured +and the local TLS implementation supports raw public keys.

      + +

      Sample commands to compute certificate and public key SHA256 digests:

      + +
      +# SHA256 digest of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -pubkey -noout |
      +    openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first private key in "pkey.pem"
      +$ openssl pkey -in pkey.pem -pubout -outform DER |
      +    openssl dgst -sha256 -c
      +
      + +

      This feature is available in Postfix 3.9 and later.

      + +
      smtp_tls_enforce_peername @@ -13296,7 +13597,9 @@ verification errors if server certificate verification is not required. With Postfix 2.8 and earlier, log the summary message and unconditionally log trust-chain verification errors. -
      2 Also log levels during TLS negotiation.
      +
      2 Also enable verbose logging in the Postfix TLS +library, log session cache operations, and enable OpenSSL logging +of the progress of the SSL handshake.
      3 Also log the hexadecimal and ASCII dump of the TLS negotiation process.
      @@ -13546,11 +13849,13 @@ lookup key, and overrides the global smtp and smtp_tls_enforce_peername settings.
      MAY
      Try to use TLS if the server announces support, -otherwise use an unencrypted connection. This has less precedence +otherwise use an unencrypted connection; after a failed TLS handshake +or TLS session, fall back to plaintext if the message has spent +minimal_backoff_time in the mail queue. This level has less precedence than a more specific result (including NONE) from the alternate host or next-hop lookup key, and has less precedence than the more specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername -= yes".
      += yes".
      MUST_NOPEERMATCH
      Require TLS encryption, but do not require that the remote SMTP server hostname matches the information @@ -13643,28 +13948,35 @@ security are:

      Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces interoperability. The optional "ciphers", "exclude", and "protocols" -attributes (available for opportunistic TLS with Postfix ≥ 2.6) -and "connection_reuse" attribute (Postfix ≥ 3.4) override the +attributes (available for opportunistic TLS with Postfix ≥ 2.6) and +"connection_reuse" attribute (Postfix ≥ 3.4) override the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols", -and -"smtp_tls_connection_reuse" configuration parameters. In the policy table, -multiple ciphers, protocols or excluded ciphers must be separated by colons, -as attribute values may not contain whitespace or commas. When opportunistic -TLS handshakes fail, Postfix retries the connection with TLS disabled. -This allows mail delivery to sites with non-interoperable TLS -implementations.
      +and "smtp_tls_connection_reuse" configuration parameters. In the policy +table, multiple ciphers, protocols or excluded ciphers must be separated +by colons, as attribute values may not contain whitespace or commas. At +this level and higher, the optional "servername" attribute (available +with Postfix ≥ 3.4) overrides the global "smtp_tls_servername" +parameter, enabling per-destination configuration of the SNI extension +sent to the remote SMTP server. The optional "enable_rpk" attribute +(Postfix ≥ 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. +When opportunistic TLS handshakes fail, Postfix retries the connection +with TLS disabled. This allows mail delivery to sites with +non-interoperable TLS implementations.
      encrypt
      -
      Mandatory TLS encryption. At this level -and higher, the optional "protocols" attribute overrides the main.cf +
      Mandatory TLS encryption. Mail is delivered only if the remote SMTP +server offers STARTTLS and the TLS handshake succeeds. At this level and +higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute -overrides the main.cf smtp_tls_mandatory_ciphers parameter, the -optional "exclude" attribute (Postfix ≥ 2.6) overrides the main.cf +overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional +"exclude" attribute (Postfix ≥ 2.6) overrides the main.cf smtp_tls_mandatory_exclude_ciphers parameter, and the optional -"connection_reuse" attribute (Postfix ≥ 3.4) overrides the -main.cf smtp_tls_connection_reuse parameter. In the policy table, -multiple ciphers, protocols or excluded ciphers must be separated by colons, -as attribute values may not contain whitespace or commas.
      +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. In the policy table, multiple +ciphers, protocols or excluded ciphers must be separated by colons, as +attribute values may not contain whitespace or commas. The optional +"enable_rpk" attribute (Postfix ≥ 3.9) overrides the main.cf +smtp_tls_enable_rpk parameter.
      dane
      Opportunistic DANE TLS. The TLS policy for the destination is @@ -13709,10 +14021,10 @@ configuration parameters. The optional "connection_reuse" attribute verification. Available with Postfix 2.5 and later. At this security level, there are no trusted Certification Authorities. The certificate trust chain, expiration date, ... are not checked. Instead, -the optional "match" attribute, or else the main.cf +the optional policy table "match" attribute, or else the main.cf smtp_tls_fingerprint_cert_match parameter, lists the certificate -fingerprints or the public key fingerprint (Postfix 2.9 and later) -of the valid server certificate. The digest +fingerprints or the public key fingerprints (Postfix 2.9 and later) +of acceptable server certificates. The digest algorithm used to calculate the fingerprint is selected by the smtp_tls_fingerprint_digest parameter. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple @@ -13723,45 +14035,58 @@ digits. The optional "ciphers", "exclude", and "protocols" attributes "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" configuration parameters. The optional "connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf smtp_tls_connection_reuse -parameter.
      +parameter. The optional "enable_rpk" attribute (Postfix ≥ 3.9) +overrides the main.cf smtp_tls_enable_rpk parameter.
      verify
      -
      Mandatory TLS verification. At this security -level, DNS MX lookups are trusted to be secure enough, and the name -verified in the server certificate is usually obtained indirectly via -unauthenticated DNS MX lookups. The optional "match" attribute overrides -the main.cf smtp_tls_verify_cert_match parameter. In the policy table, -multiple match patterns and strategies must be separated by colons. -In practice explicit control over matching is more common with the -"secure" policy, described below. The optional "ciphers", "exclude", -and "protocols" attributes (Postfix ≥ 2.6) override the -"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and -"smtp_tls_mandatory_protocols" configuration parameters. The optional -"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf -smtp_tls_connection_reuse parameter.
      +
      Mandatory TLS verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups are presumed to be +secure enough, and the name verified in the server certificate is +potentially obtained via unauthenticated DNS MX lookups. The optional +"match" attribute overrides the main.cf smtp_tls_verify_cert_match +parameter. In the policy table, multiple match patterns and strategies +must be separated by colons. In practice explicit control over matching +is more common with the "secure" policy, described below. The optional +"ciphers", "exclude", and "protocols" attributes (Postfix ≥ 2.6) +override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix ≥ 2.11 the optional "tafile" +policy table attribute modifies trust chain verification in the same +manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile" +attribute may be specified multiple times to load multiple trust-anchor +files. The optional "connection_reuse" attribute (Postfix ≥ 3.4) +overrides the main.cf smtp_tls_connection_reuse parameter.
      secure
      -
      Secure-channel TLS. At this security level, DNS -MX lookups, though potentially used to determine the candidate next-hop -gateway IP addresses, are not trusted to be secure enough for TLS -peername verification. Instead, the default name verified in the server -certificate is obtained directly from the next-hop, or is explicitly -specified via the optional "match" attribute which overrides the -main.cf smtp_tls_secure_cert_match parameter. In the policy table, -multiple match patterns and strategies must be separated by colons. -The match attribute is most useful when multiple domains are supported by -a common server: the policy entries for additional domains specify matching -rules for the primary domain certificate. While transport table overrides -that route the secondary domains to the primary nexthop also allow secure -verification, they risk delivery to the wrong destination when domains -change hands or are re-assigned to new gateways. With the "match" -attribute approach, routing is not perturbed, and mail is deferred if -verification of a new MX host fails. The optional "ciphers", "exclude", -and "protocols" attributes (Postfix ≥ 2.6) override the -"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and -"smtp_tls_mandatory_protocols" configuration parameters. The optional -"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf -smtp_tls_connection_reuse parameter.
      +
      Secure certificate verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups, though potentially +used to determine the candidate next-hop gateway IP addresses, are +not presumed to be secure enough for TLS peername verification. +Instead, the default name verified in the server certificate is obtained +directly from the next-hop, or is explicitly specified via the optional +"match" attribute which overrides the main.cf smtp_tls_secure_cert_match +parameter. In the policy table, multiple match patterns and strategies +must be separated by colons. The match attribute is most useful when +multiple domains are supported by a common server: the policy entries +for additional domains specify matching rules for the primary domain +certificate. While transport table overrides that route the secondary +domains to the primary nexthop also allow secure verification, they risk +delivery to the wrong destination when domains change hands or are +re-assigned to new gateways. With the "match" attribute approach, +routing is not perturbed, and mail is deferred if verification of a new +MX host fails. The optional "ciphers", "exclude", and "protocols" +attributes (Postfix ≥ 2.6) override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix ≥ 2.11 the "tafile" attribute +optionally modifies trust chain verification in the same manner as the +"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be +specified multiple times to load multiple trust-anchor files. The +optional "connection_reuse" attribute (Postfix ≥ 3.4) overrides the +main.cf smtp_tls_connection_reuse parameter.
      @@ -13807,7 +14132,7 @@ configurations in environments where DNS security is not assured.

      smtp_tls_protocols -(default: see postconf -d output)
      +(default: see 'postconf -d' output)

      TLS protocols that the Postfix SMTP client will use with opportunistic TLS encryption. In main.cf the values are separated by @@ -13975,7 +14300,9 @@ destinations via smtp_tls_policy_

      may
      Opportunistic TLS. Use TLS if this is supported by the remote -SMTP server, otherwise use plaintext. Since +SMTP server, otherwise use plaintext; after a failed TLS handshake +or TLS session, fall back to plaintext if the message has spent +minimal_backoff_time in the mail queue. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces interoperability. The "smtp_tls_ciphers" and "smtp_tls_protocols" (Postfix ≥ 2.6) @@ -14896,9 +15223,8 @@ pubkey_fingerprint } }
      check_client_access type:table
      -
      Search the specified access database for the client hostname, -parent domains, client IP address, or networks obtained by stripping -least significant octets. See the access(5) manual page for details.
      +
      Search the specified access database for the client hostname +or IP address. See the access(5) manual page for details.
      check_client_a_access type:table
      @@ -14929,8 +15255,7 @@ available in Postfix 2.7 and later.
      check_reverse_client_hostname_access type:table
      Search the specified access database for the unverified reverse -client hostname, parent domains, client IP address, or networks -obtained by stripping least significant octets. See the access(5) +client hostname or IP address. See the access(5) manual page for details. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from denylists. This feature is available in Postfix 2.6 @@ -15527,6 +15852,9 @@ server. This option is therefore off by default.

      STARTTLS due to insufficient privileges to access the server private key. This is intended behavior.

      +

      This feature is deprecated as of Postfix 3.9. Specify +smtpd_tls_security_level instead.

      +

      This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead.

      @@ -15588,8 +15916,8 @@ received with the ETRN command.
      check_etrn_access type:table
      -
      Search the specified access database for the ETRN domain name -or its parent domains. See the access(5) manual page for details. +
      Search the specified access database for the ETRN domain name. +See the access(5) manual page for details.
      @@ -15641,7 +15969,7 @@ This feature is available in Postfix 2.0 and later.
      smtpd_forbid_bare_newline -(default: Postfix < 3.9: no)
      +(default: Postfix ≥ 3.9: normalize)

      Reject or restrict input lines from an SMTP client that end in <LF> instead of the standard <CR><LF>. Such line @@ -15654,7 +15982,8 @@ SMTP smuggling.

      -
      normalize
      Require the standard +
      normalize (default for Postfix ≥ 3.9)
      +
      Require the standard End-of-DATA sequence <CR><LF>.<CR><LF>. Otherwise, allow command or message content lines ending in the non-standard <LF>, and process them as if the client sent the @@ -15666,6 +15995,13 @@ with the standard End-of-DATA sequence <CR><LF>.<CR><LF>.

      Such clients can be excluded with smtpd_forbid_bare_newline_exclusions.
      +
      note
      Same as "normalize", but also notes in +the log whether the Postfix SMTP server received any lines with +"bare <LF>". The information is formatted as "disconnect +from name[address] ... notes=bare_lf". The notes value is +expected to become a list of comma-separated names.

      This +feature is available in Postfix 3.9 and later.
      +
      yes
      Compatibility alias for normalize.
      reject
      Require the standard End-of-DATA @@ -15684,8 +16020,8 @@ of BDAT violations, BDAT can be selectively disabled with smtpd_discard_ehlo_keyword_address_maps, or globally disabled with smtpd_discard_ehlo_keywords).
      -
      no (default)
      Do not require the standard -End-of-DATA +
      no (default for Postfix < 3.9)
      +
      Do not require the standard End-of-DATA sequence <CR><LF>.<CR><LF>. Always process a bare <LF> as if the client sent <CR><LF>. This option is fully backwards compatible, but is not recommended for @@ -15793,9 +16129,9 @@ Specify a 5XX status code (521 to disconnect).

      Disconnect remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. The server replies with "554 5.5.0 Error: SMTP protocol synchronization" and logs the unexpected remote -SMTP client input. Specify "smtpd_forbid_unauth_pipelining = yes" -to enable. This feature is enabled by default with Postfix ≥ -3.9.

      +SMTP client input. This feature is enabled by default with Postfix +≥ 3.9. Specify "smtpd_forbid_unauth_pipelining = no" to disable. +

      This feature is available in Postfix ≥ 3.9, 3.8.1, 3.7.6, 3.6.10, and 3.5.20.

      @@ -15899,7 +16235,7 @@ received with the HELO or EHLO command.
      check_helo_access type:table
      Search the specified access(5) database for the HELO or EHLO -hostname or parent domains, and execute the corresponding action. +hostname, and execute the corresponding action. Note: specify "smtpd_helo_required = yes" to fully enforce this restriction (without "smtpd_helo_required = yes", a client can simply skip check_helo_access by not sending HELO or EHLO).
      @@ -16563,8 +16899,7 @@ that is received with the RCPT TO command.
      check_recipient_access type:table
      Search the specified access(5) database for the resolved RCPT -TO address, domain, parent domains, or localpart@, and execute the -corresponding action.
      +TO address, and execute the corresponding action.
      check_recipient_a_access type:table
      @@ -16993,7 +17328,7 @@ The same restrictions are available as documented under smtpd_recipient_restrictions.

      -

      This feature is available in Postix 2.10 and later.

      +

      This feature is available in Postfix 2.10 and later.

      @@ -17411,8 +17746,7 @@ received with the MAIL FROM command.
      check_sender_access type:table
      Search the specified access(5) database for the MAIL FROM -address, domain, parent domains, or localpart@, and execute the -corresponding action.
      +address, and execute the corresponding action.
      check_sender_a_access type:table
      @@ -18314,6 +18648,53 @@ compiled and linked with OpenSSL 1.0.0 or later on platforms where EC algorithms have not been disabled by the vendor.

      + + +
      smtpd_tls_enable_rpk +(default: no)
      + +

      Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking for or requiring client +authentication. This feature is ignored when there is no raw public +key support in the local TLS implementation.

      + +

      The Postfix SMTP server will log a warning when "smtpd_tls_enable_rpk += yes", but the remote SMTP client sends a certificate, the +certificate's public key fingerprint does not match a check_ccert_access +table, while the certificate fingerprint does match a check_ccert_access +table. The remote SMTP client would lose access when it starts +sending a raw public key instead of a certificate, after its TLS +implementation is updated with raw public key support.

      + +

      The Postfix SMTP server always sends a raw public key instead +of a certificate, if solicited by the remote SMTP client and the +local TLS implementation supports raw public keys. If the client +sends a server name indication with an SNI TLS extension, and +tls_server_sni_maps is configured, the server will extract a raw +public key from the indicated certificate.

      + +

      Sample commands to compute certificate and public key SHA256 digests:

      + +
      +# SHA256 digest of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -pubkey -noout |
      +    openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first private key in "pkey.pem"
      +$ openssl pkey -in pkey.pem -pubout -outform DER |
      +    openssl dgst -sha256 -c
      +
      + +

      This feature is available in Postfix 3.9 and later.

      + +
      smtpd_tls_exclude_ciphers @@ -18472,7 +18853,9 @@ if client certificate verification is not required. With Postfix 2.8 and earlier, log the summary message, peer certificate summary information and unconditionally log trust-chain verification errors. -
      2 Also log levels during TLS negotiation.
      +
      2 Also enable verbose logging in the Postfix TLS +library, log session cache operations, and enable OpenSSL logging +of the progress of the SSL handshake.
      3 Also log hexadecimal and ASCII dump of TLS negotiation process.
      @@ -18655,7 +19038,7 @@ releases ≥ 3.0.14, 3.1.10, 3.2.7 and 3.3.2).

      smtpd_tls_protocols -(default: see postconf -d output)
      +(default: see 'postconf -d' output)

      TLS protocols accepted by the Postfix SMTP server with opportunistic TLS encryption. If the list is empty, the server supports all available @@ -18931,6 +19314,9 @@ but do not require that clients use TLS encryption.

      STARTTLS due to insufficient privileges to access the server private key. This is intended behavior.

      +

      This feature is deprecated as of Postfix 3.9. Specify +smtpd_tls_security_level instead.

      +

      This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead.

      @@ -19438,8 +19824,7 @@ via the tls_config_file parameter. selected name is not present in the configuration file, the default application name ("openssl_conf") is used as a fallback.

      -

      This feature is available in Postfix ≥ 3.9, 3.8.1, 3.7.6, -3.6.10, and 3.5.20.

      +

      This feature is available in Postfix ≥ 3.9.

      @@ -20356,6 +20741,9 @@ to configure tlsproxy client keys and certificates is via the See smtp_enforce_tls for further details. Use tlsproxy_client_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_security_level instead.

      +

      This feature is available in Postfix 3.4 and later.

      @@ -20427,6 +20815,9 @@ value.

      usage policy by next-hop destination and by remote TLS server hostname. See smtp_tls_per_site for further details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_policy_maps instead.

      +

      This feature is available in Postfix 3.4 and later.

      @@ -20488,6 +20879,9 @@ was previously called tlsproxy_c support. See smtp_use_tls for further details. Use tlsproxy_client_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_security_level instead.

      +

      This feature is available in Postfix 3.4 and later.

      @@ -20500,6 +20894,9 @@ support. See smtp_use_tls for further require that clients use TLS encryption. See smtpd_enforce_tls for further details. Use tlsproxy_tls_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_tls_security_level instead.

      +

      This feature is available in Postfix 2.8 and later.

      @@ -20632,6 +21029,8 @@ private DSA key. DSA is obsolete and should not be used. See should use with non-export EDH ciphers. See smtpd_tls_dh1024_param_file for further details.

      +

      This feature is deprecated as of Postfix 3.9. Do not specify.

      +

      This feature is available in Postfix 2.8 and later.

      @@ -20704,9 +21103,23 @@ the "tlsproxy_tls_chain_files elliptic-curve Diffie-Hellman (EECDH) key exchange. See smtpd_tls_eecdh_grade for further details.

      +

      This feature is deprecated as of Postfix 3.9. Do not specify.

      +

      This feature is available in Postfix 2.8 and later.

      + + +
      tlsproxy_tls_enable_rpk +(default: $smtpd_tls_enable_rpk)
      + +

      Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking or requiring client +authentication. See $smtpd_tls_enable_rpk for details.

      + +

      This feature is available in Postfix 3.9 and later.

      + +
      tlsproxy_tls_exclude_ciphers @@ -20856,6 +21269,9 @@ shared by all three services, namely smtpd_use_tls for further details. Use tlsproxy_tls_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_tls_security_level instead.

      +

      This feature is available in Postfix 2.8 and later.

      @@ -21100,7 +21516,14 @@ built-in suffix (in this case: "_initial_destination_concurrency").

      Optional lookup tables with mappings from recipient address to (message delivery transport, next-hop destination). See transport(5) -for details. +for syntax details. +

      + +

      This information may override the message delivery transport +and/or next-hop destination that are specified with $local_transport, +$virtual_transport, $relay_transport, $default_transport, +$sender_dependent_relayhost_maps, $relayhost, +$sender_dependent_default_transport_maps, or the recipient domain.

      @@ -21735,7 +22158,7 @@ This feature is available in Postfix 1.1 and later.

      The maximal length of an email address after virtual alias expansion. -This stops virtual aliasing loops that increase the address length +This stops virtual aliasing loops that increase the address length exponentially.

      @@ -21814,8 +22237,10 @@ This feature is available in Postfix 2.1 and later. (default: $virtual_maps)

      -Optional lookup tables that alias specific mail addresses or domains -to other local or remote addresses. The table format and lookups +Optional lookup tables with aliases that apply to all recipients: +local(8), virtual, and remote; this is unlike alias_maps that apply +only to local(8) recipients. +The table format and lookups are documented in virtual(5). For an overview of Postfix address manipulations see the ADDRESS_REWRITING_README document.

      diff --git a/html/postdrop.1.html b/html/postdrop.1.html index 72a4abf..bc4293a 100644 --- a/html/postdrop.1.html +++ b/html/postdrop.1.html @@ -70,7 +70,7 @@ POSTDROP(1) POSTDROP(1) figuration files. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix + The list of environment variables that a privileged Postfix process will import from a non-Postfix parent process, or name=value environment overrides. diff --git a/html/postfix-manuals.html b/html/postfix-manuals.html index 7ddfa73..84774a5 100644 --- a/html/postfix-manuals.html +++ b/html/postfix-manuals.html @@ -135,7 +135,7 @@ the following convention:

    • access(5), Postfix SMTP access control table -
    • aliases(5), Postfix alias database +
    • aliases(5), Postfix local aliasing
    • canonical(5), Postfix input address rewriting @@ -147,7 +147,7 @@ the following convention:

    • transport(5), Postfix routing table -
    • virtual(5), Postfix virtual aliasing +
    • virtual(5), Postfix virtual aliasing @@ -164,6 +164,8 @@ the following convention:

    • memcache_table(5), Postfix memcache client +
    • mongodb_table(5), Postfix MongoDB client +
    • mysql_table(5), Postfix MYSQL client
    • nisplus_table(5), Postfix NIS+ client diff --git a/html/postfix.1.html b/html/postfix.1.html index 4654071..a6ede78 100644 --- a/html/postfix.1.html +++ b/html/postfix.1.html @@ -346,19 +346,20 @@ POSTFIX(1) POSTFIX(1) Table-driven mechanisms: access(5), Postfix SMTP access control table - aliases(5), Postfix alias database + aliases(5), Postfix local aliasing canonical(5), Postfix input address rewriting generic(5), Postfix output address rewriting header_checks(5), body_checks(5), Postfix content inspection relocated(5), Users that have moved transport(5), Postfix routing table - virtual(5), Postfix virtual aliasing + virtual(5), Postfix virtual aliasing Table lookup mechanisms: cidr_table(5), Associate CIDR pattern with value ldap_table(5), Postfix LDAP client lmdb_table(5), Postfix LMDB database driver memcache_table(5), Postfix memcache client + mongodb_table(5), Postfix MongoDB client mysql_table(5), Postfix MYSQL client nisplus_table(5), Postfix NIS+ client pcre_table(5), Associate PCRE pattern with value diff --git a/html/postkick.1.html b/html/postkick.1.html index 3156fc4..9ca7c59 100644 --- a/html/postkick.1.html +++ b/html/postkick.1.html @@ -63,7 +63,7 @@ POSTKICK(1) POSTKICK(1) the Postfix daemon process input buffer before giving up. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix + The list of environment variables that a privileged Postfix process will import from a non-Postfix parent process, or name=value environment overrides. diff --git a/html/postlock.1.html b/html/postlock.1.html index 0ca0b57..9750f9b 100644 --- a/html/postlock.1.html +++ b/html/postlock.1.html @@ -93,7 +93,7 @@ POSTLOCK(1) POSTLOCK(1) figuration files. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix + The list of environment variables that a privileged Postfix process will import from a non-Postfix parent process, or name=value environment overrides. diff --git a/html/postlog.1.html b/html/postlog.1.html index 587edbc..617b78b 100644 --- a/html/postlog.1.html +++ b/html/postlog.1.html @@ -90,6 +90,13 @@ POSTLOG(1) POSTLOG(1) postlog_service_name (postlog) The name of the postlogd(8) service entry in master.cf. + Available in Postfix 3.9 and later: + + maillog_file_permissions (0600) + The file access permissions that will be set when the file + $maillog_file is created for the first time, or when the file is + created after an existing file is rotated. + SEE ALSO postconf(5), configuration parameters postlogd(8), Postfix logging diff --git a/html/postlogd.8.html b/html/postlogd.8.html index 58cdf01..e0a72af 100644 --- a/html/postlogd.8.html +++ b/html/postlogd.8.html @@ -36,9 +36,9 @@ POSTLOGD(8) POSTLOGD(8) postqueue(1) and (Postfix >= 3.7) postlog(1). CONFIGURATION PARAMETERS - Changes to main.cf are picked up automatically, as postlogd(8) pro- - cesses run for only a limited amount of time. Use the command "postfix - reload" to speed up a change. + Changes to main.cf are not picked up automatically, because postlogd(8) + terminates only after reaching the max_idle time limit. Use the com- + mand "postfix reload" to speed up a change. The text below provides only a parameter summary. See postconf(5) for more details including examples. @@ -68,6 +68,13 @@ POSTLOGD(8) POSTLOGD(8) How much time a postlogd(8) process may take to process a request before it is terminated by a built-in watchdog timer. + Available in Postfix 3.9 and later: + + maillog_file_permissions (0600) + The file access permissions that will be set when the file + $maillog_file is created for the first time, or when the file is + created after an existing file is rotated. + SEE ALSO postconf(5), configuration parameters syslogd(8), system logging diff --git a/html/postscreen.8.html b/html/postscreen.8.html index 3511a9c..9ab10b7 100644 --- a/html/postscreen.8.html +++ b/html/postscreen.8.html @@ -315,31 +315,35 @@ POSTSCREEN(8) POSTSCREEN(8) porary allowlist entry before it is removed. postscreen_bare_newline_ttl (30d) - The amount of time that postscreen(8) will use the result from a - successful "bare newline" SMTP protocol test. + The amount of time that postscreen(8) remembers that a client IP + address passed a "bare newline" SMTP protocol test, before it + address is required to pass that test again. postscreen_dnsbl_max_ttl (${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h) - The maximum amount of time that postscreen(8) will use the - result from a successful DNS-based reputation test before a - client IP address is required to pass that test again. + The maximum amount of time that postscreen(8) remembers that a + client IP address passed a DNS-based reputation test, before it + is required to pass that test again. postscreen_dnsbl_min_ttl (60s) - The minimum amount of time that postscreen(8) will use the - result from a successful DNS-based reputation test before a - client IP address is required to pass that test again. + The minimum amount of time that postscreen(8) remembers that a + client IP address passed a DNS-based reputation test, before it + is required to pass that test again. postscreen_greet_ttl (1d) - The amount of time that postscreen(8) will use the result from a - successful PREGREET test. + The amount of time that postscreen(8) remembers that a client IP + address passed a PREGREET test, before it is required to pass + that test again. postscreen_non_smtp_command_ttl (30d) - The amount of time that postscreen(8) will use the result from a - successful "non_smtp_command" SMTP protocol test. + The amount of time that postscreen(8) remembers that a client IP + address passed a "non_smtp_command" SMTP protocol test, before + it is required to pass that test again. postscreen_pipelining_ttl (30d) - The amount of time that postscreen(8) will use the result from a - successful "pipelining" SMTP protocol test. + The amount of time that postscreen(8) remembers that a client IP + address passed a "pipelining" SMTP protocol test, before it is + required to pass that test again. RESOURCE CONTROLS line_length_limit (2048) diff --git a/html/postsuper.1.html b/html/postsuper.1.html index 30a524a..cf0681a 100644 --- a/html/postsuper.1.html +++ b/html/postsuper.1.html @@ -275,7 +275,7 @@ POSTSUPER(1) POSTSUPER(1) subdirectory levels. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix + The list of environment variables that a privileged Postfix process will import from a non-Postfix parent process, or name=value environment overrides. diff --git a/html/posttls-finger.1.html b/html/posttls-finger.1.html index 2ed629a..a1475ca 100644 --- a/html/posttls-finger.1.html +++ b/html/posttls-finger.1.html @@ -112,7 +112,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) ified in the DNS). In Postfix versions prior to 3.6, the default value was "md5". - -f Lookup the associated DANE TLSA RRset even when a hostname is + -f Look up the associated DANE TLSA RRset even when a hostname is not an alias and its address records lie in an unsigned zone. See smtp_tls_force_insecure_host_tlsa_lookup for details. @@ -302,6 +302,16 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) protocol. The destination domain:port must of course provide such a service. + -x Prefer RFC7250 non-X.509 raw public key (RPK) server creden- + tials. By default only X.509 certificates are accepted. This + is analogous to setting smtp_tls_enable_rpk = yes in the smtp(8) + client. At the fingerprint security level, when raw public keys + are enabled, only public key (and not certificate) fingerprints + will be compared against the specified list of match arguments. + Certificate fingerprints are fragile when raw public keys are + solicited, the server may at some point in time start returning + only the public key. + -X Enable tlsproxy(8) mode. This is an unsupported mode, for pro- gram development only. diff --git a/html/proxymap.8.html b/html/proxymap.8.html index 7c98c47..a1f2f18 100644 --- a/html/proxymap.8.html +++ b/html/proxymap.8.html @@ -41,7 +41,7 @@ PROXYMAP(8) PROXYMAP(8) o To provide single-updater functionality for lookup tables that do not reliably support multiple writers (i.e. all file-based - tables). + tables that are not based on lmdb). The proxymap(8) server implements the following requests: diff --git a/html/qmgr.8.html b/html/qmgr.8.html index bfaa05f..068b256 100644 --- a/html/qmgr.8.html +++ b/html/qmgr.8.html @@ -232,8 +232,8 @@ QMGR(8) QMGR(8) ter.cf name of the message delivery transport. default_recipient_refill_delay (5s) - The default per-transport maximum delay between recipients - refills. + The default per-transport maximum delay between refilling recip- + ients. transport_recipient_refill_delay ($default_recipient_refill_delay) A transport-specific override for the default_recipi- diff --git a/html/qmqpd.8.html b/html/qmqpd.8.html index 9506cfa..55cbcdc 100644 --- a/html/qmqpd.8.html +++ b/html/qmqpd.8.html @@ -61,7 +61,7 @@ QMQPD(8) QMQPD(8) smtputf8_enable (yes) Enable preliminary SMTPUTF8 support for the protocols described - in RFC 6531..6533. + in RFC 6531, RFC 6532, and RFC 6533. smtputf8_autodetect_classes (sendmail, verify) Detect that a message requires SMTPUTF8 support for the speci- diff --git a/html/regexp_table.5.html b/html/regexp_table.5.html index 05cda13..96e4b38 100644 --- a/html/regexp_table.5.html +++ b/html/regexp_table.5.html @@ -148,8 +148,12 @@ REGEXP_TABLE(5) REGEXP_TABLE(5) Postfix parses the result as if it is a file in /etc/postfix. - Note: if a rule contains $, specify $$ to keep Postfix from trying to - do $name expansion as it evaluates a parameter value. + Note: if an inlined rule contains $, specify $$ to keep Postfix from + trying to do $name expansion as it evaluates a parameter value. + + Note: when using $name inside an inlined pattern, this will not disable + metacharacters such as '.' in the $name expansion. To prevent unex- + pected matches, use a pcre: table, and specify \Q$name\E. EXAMPLE SMTPD ACCESS MAP # Disallow sender-specified routing. This is a must if you relay mail diff --git a/html/relocated.5.html b/html/relocated.5.html index efd2f53..62a580a 100644 --- a/html/relocated.5.html +++ b/html/relocated.5.html @@ -125,8 +125,8 @@ RELOCATED(5) RELOCATED(5) Other parameters of interest: inet_interfaces (all) - The network interface addresses that this mail system receives - mail on. + The local network interface addresses that this mail system + receives mail on. mydestination ($myhostname, localhost.$mydomain, localhost) The list of domains that are delivered via the $local_transport @@ -137,8 +137,9 @@ RELOCATED(5) RELOCATED(5) and that locally posted mail is delivered to. proxy_interfaces (empty) - The network interface addresses that this mail system receives - mail on by way of a proxy or network address translation unit. + The remote network interface addresses that this mail system + receives mail on by way of a proxy or network address transla- + tion unit. SEE ALSO trivial-rewrite(8), address resolver diff --git a/html/sendmail.1.html b/html/sendmail.1.html index bebc17b..bf6051d 100644 --- a/html/sendmail.1.html +++ b/html/sendmail.1.html @@ -455,9 +455,11 @@ SENDMAIL(1) SENDMAIL(1) The location of the Postfix top-level queue directory. remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and - append the specified domain name to incomplete addresses. + Rewrite or add message headers in mail from remote clients if + the remote_header_rewrite_domain parameter value is non-empty, + updating incomplete addresses with the domain specified in the + remote_header_rewrite_domain parameter, and adding missing head- + ers. syslog_facility (mail) The syslog facility of Postfix logging. diff --git a/html/smtp-source.1.html b/html/smtp-source.1.html index db9a17b..6311971 100644 --- a/html/smtp-source.1.html +++ b/html/smtp-source.1.html @@ -49,7 +49,7 @@ SMTP-SOURCE(1) SMTP-SOURCE(1) over the same connection. -f from - Use the specified sender address (default: <foo@myhostname>). + Use the specified sender address (default: <foo@my-hostname>). -F file Send the pre-formatted message header and body in the specified @@ -65,28 +65,42 @@ SMTP-SOURCE(1) SMTP-SOURCE(1) -m message_count Send the specified number of messages (default: 1). - -M myhostname + -M my-hostname Use the specified hostname or [address] in the HELO command and in the default sender and recipient addresses, instead of the machine hostname. - -N Prepend a non-repeating sequence number to each recipient - address. This avoids the artificial 100% hit rate in the resolve - and rewrite client caches and exercises the trivial-rewrite dae- - mon, better approximating Postfix performance under real-life - work-loads. + -N Generate each recipient address by appending a number (a + per-process recipient counter) to the recipient address local- + part specified with the -t option. + + Note: to use the number as an address extension, specify an + explicit address delimiter at the end of the recipient local- + part, as in "-t localpart+@domain" or "-t localpart+", where "+" + is a Postfix recipient address delimiter. + + Benefits: + + o A non-constant recipient address avoids an unrealistic + 100% cache hit rate in clients of the Postfix trivial-re- + write service, better approximating performance under + real-life work-loads. + + o A fixed recipient address local-part with a non-constant + address extension avoids the need to configure a large + number of valid recipient addresses in the receiving + Postfix server. -o Old mode: don't send HELO, and don't send message headers. -r recipient_count - Send the specified number of recipients per transaction - (default: 1). Recipient names are generated by prepending a - number to the recipient address. + Send the specified number of recipients per transaction + (default: 1), and generate recipient addresses as described + under the -N option. -R interval - Wait for a random period of time 0 <= n <= interval between mes- - sages. Suspending one thread does not affect other delivery - threads. + Wait a random time (0 <= n <= interval) between messages. Sus- + pending one thread does not affect other delivery threads. -s session_count Run the specified number of SMTP sessions in parallel (default: @@ -95,7 +109,8 @@ SMTP-SOURCE(1) SMTP-SOURCE(1) -S subject Send mail with the named subject line (default: none). - -t to Use the specified recipient address (default: <foo@myhostname>). + -t to Use the specified recipient address (default: <foo@my-host- + name>). -T windowsize Override the default TCP window size. To work around broken TCP diff --git a/html/smtp.8.html b/html/smtp.8.html index 1144ee8..4cc187c 100644 --- a/html/smtp.8.html +++ b/html/smtp.8.html @@ -5,88 +5,100 @@ Postfix manual - smtp(8)
      -SMTP(8)                                                                SMTP(8)
      +SMTP,(LMTP)                                                        SMTP,(LMTP)
       
       NAME
      -       smtp - Postfix SMTP+LMTP client
      +       smtp, lmtp - Postfix SMTP+LMTP client
       
       SYNOPSIS
              smtp [generic Postfix daemon options] [flags=DORX]
       
      +       lmtp [generic Postfix daemon options] [flags=DORX]
      +
       DESCRIPTION
              The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery
              protocols. It processes message delivery requests from the  queue  man-
              ager.  Each  request specifies a queue file, a sender address, a domain
              or host to deliver to, and recipient information.  This program expects
      -       to be run from the master(8) process manager.
      +       to be run from the master(8) process manager. The process name, smtp or
      +       lmtp, controls the protocol, and the names of the configuration parame-
      +       ters that will be used.
       
              The  SMTP+LMTP  client  updates  the queue file and marks recipients as
              finished, or it informs the queue manager that delivery should be tried
              again  at  a  later  time.  Delivery  status  reports  are  sent to the
              bounce(8), defer(8) or trace(8) daemon as appropriate.
       
      -       The SMTP+LMTP client looks up a list of mail  exchanger  addresses  for
      -       the  destination  host,  sorts  the list by preference, and connects to
      -       each listed address until it finds a server that responds.
      -
      -       When a server is not reachable, or when mail delivery fails  due  to  a
      -       recoverable  error  condition, the SMTP+LMTP client will try to deliver
      -       the mail to an alternate host.
      +       The server lookup strategy is different for SMTP and LMTP, as described
      +       in the sections "SMTP SERVER LOOKUP" and "LMTP SERVER LOOKUP".
       
      -       After a successful mail transaction, a connection may be saved  to  the
      -       scache(8)  connection  cache  server,  so  that  it  may be used by any
      +       After  a  successful mail transaction, a connection may be saved to the
      +       scache(8) connection cache server, so  that  it  may  be  used  by  any
              SMTP+LMTP client for a subsequent transaction.
       
      -       By default, connection caching is enabled temporarily for  destinations
      +       By  default, connection caching is enabled temporarily for destinations
              that have a high volume of mail in the active queue. Connection caching
              can be enabled permanently for specific destinations.
       
      -SMTP DESTINATION SYNTAX
      -       The Postfix SMTP+LMTP client supports multiple  destinations  separated
      -       by comma or whitespace (Postfix 3.5 and later).  SMTP destinations have
      -       the following form:
      +SMTP SERVER LOOKUP
      +       The  Postfix  SMTP  client  supports multiple destinations separated by
      +       comma or whitespace (Postfix 3.5 and later).  Each destination is tried
      +       in the specified order.
      +
      +       SMTP destinations have the following form:
       
              domainname
       
      -       domainname:port
      -              Look up the mail exchangers for the specified domain,  and  con-
      -              nect to the specified port (default: smtp).
      +       domainname:service
      +              Look  up  the mail exchangers for the specified domain, and con-
      +              nect to the specified service (default: smtp).  Optionally, mail
      +              exchangers may be looked up with SRV queries instead of MX; this
      +              requires that service is given in symbolic form.
       
              [hostname]
       
      -       [hostname]:port
      -              Look  up  the  address(es) of the specified host, and connect to
      -              the specified port (default: smtp).
      +       [hostname]:service
      +              Look up the address(es) for the specified host, and  connect  to
      +              the specified service (default: smtp).
       
              [address]
       
      -       [address]:port
      +       [address]:service
                     Connect to the host at the specified address, and connect to the
      -              specified  port (default: smtp). An IPv6 address must be format-
      -              ted as [ipv6:address].
      +              specified service (default: smtp). An IPv6 address must be  for-
      +              matted as [ipv6:address].
       
      -LMTP DESTINATION SYNTAX
      -       The Postfix SMTP+LMTP client supports multiple  destinations  separated
      -       by comma or whitespace (Postfix 3.5 and later).  LMTP destinations have
      -       the following form:
      +LMTP SERVER LOOKUP
      +       The  Postfix  LMTP  client  supports multiple destinations separated by
      +       comma or whitespace (Postfix 3.5 and later).  Each destination is tried
      +       in the specified order.
      +
      +       LMTP destinations have the following form:
       
              unix:pathname
      -              Connect to the local UNIX-domain server that  is  bound  to  the
      -              specified  pathname.  If  the process runs chrooted, an absolute
      +              Connect  to  the  local  UNIX-domain server that is bound to the
      +              specified pathname. If the process runs  chrooted,  an  absolute
                     pathname is interpreted relative to the Postfix queue directory.
       
      +       inet:domainname
      +
      +       inet:domainname:service
      +              Look up the LMTP servers for the specified  domain  and  service
      +              (default:  lmtp).   This  form is supported when SRV lookups are
      +              enabled, and requires that service is in symbolic form.
      +
              inet:hostname
       
      -       inet:hostname:port
      +       inet:hostname:service
      +              Look up the address(es) for the specified host, and  connect  to
      +              the  specified  service  (default:  lmtp).  When SRV lookups are
      +              enabled, use the form [hostname] to force address lookups.
       
              inet:[address]
       
      -       inet:[address]:port
      -              Connect  to  the  specified  TCP  port on the specified local or
      -              remote host. If no  port  is  specified,  connect  to  the  port
      -              defined  as  lmtp  in services(4).  If no such service is found,
      -              the lmtp_tcp_port configuration parameter (default value of  24)
      -              will   be   used.    An   IPv6  address  must  be  formatted  as
      +       inet:[address]:service
      +              Connect to the  specified  local  or  remote  host  and  service
      +              (default:   lmtp).    An  IPv6  address  must  be  formatted  as
                     [ipv6:address].
       
       SINGLE-RECIPIENT DELIVERY
      @@ -136,10 +148,9 @@ SMTP(8)                                                                SMTP(8)
                            This feature is available as of Postfix 3.5.
       
       SECURITY
      -       The SMTP+LMTP client is moderately security-sensitive. It
      -       talks to SMTP or LMTP servers and to DNS servers on the
      -       network. The SMTP+LMTP client can be run chrooted at fixed
      -       low privilege.
      +       The SMTP+LMTP client is moderately security-sensitive. It talks to SMTP
      +       or LMTP servers and to DNS servers on the network. The SMTP+LMTP client
      +       can be run chrooted at fixed low privilege.
       
       STANDARDS
              RFC 821 (SMTP protocol)
      @@ -180,20 +191,19 @@ SMTP(8)                                                                SMTP(8)
              for all destinations that map onto the same IP address and TCP port.
       
       CONFIGURATION PARAMETERS
      -       Before Postfix version 2.3, the LMTP client is a separate program  that
      -       implements  only  a  subset  of  the functionality available with SMTP:
      -       there is no support for TLS, and  connections  are  cached  in-process,
      -       making it ineffective when the client is used for multiple domains.
      +       Postfix versions 2.3 and later implement the SMTP and LMTP client  with
      +       the  same program, and choose the protocol and configuration parameters
      +       based on the process name, smtp or lmtp.
       
              Most smtp_xxx configuration parameters have an lmtp_xxx "mirror" param-
      -       eter for the equivalent LMTP  feature.  This  document  describes  only
      +       eter  for  the  equivalent  LMTP  feature. This document describes only
              those LMTP-related parameters that aren't simply "mirror" parameters.
       
      -       Changes  to  main.cf  are picked up automatically, as smtp(8) processes
      +       Changes to main.cf are picked up automatically,  as  smtp(8)  processes
              run for only a limited amount of time. Use the command "postfix reload"
              to speed up a change.
       
      -       The  text  below provides only a parameter summary. See postconf(5) for
      +       The text below provides only a parameter summary. See  postconf(5)  for
              more details including examples.
       
       COMPATIBILITY CONTROLS
      @@ -214,8 +224,8 @@ SMTP(8)                                                                SMTP(8)
                     will send via SMTP.
       
              smtp_pix_workaround_delay_time (10s)
      -              How  long  the  Postfix  SMTP  client  pauses   before   sending
      -              ".<CR><LF>"   in   order   to   work  around  the  PIX  firewall
      +              How   long   the  Postfix  SMTP  client  pauses  before  sending
      +              ".<CR><LF>"  in  order  to  work   around   the   PIX   firewall
                     "<CR><LF>.<CR><LF>" bug.
       
              smtp_pix_workaround_threshold_time (500s)
      @@ -224,19 +234,19 @@ SMTP(8)                                                                SMTP(8)
                     delivery through firewalls with "smtp fixup" mode turned on.
       
              smtp_pix_workarounds (disable_esmtp, delay_dotcrlf)
      -              A list that specifies zero or more  workarounds  for  CISCO  PIX
      +              A  list  that  specifies  zero or more workarounds for CISCO PIX
                     firewall bugs.
       
              smtp_pix_workaround_maps (empty)
      -              Lookup  tables,  indexed by the remote SMTP server address, with
      +              Lookup tables, indexed by the remote SMTP server  address,  with
                     per-destination workarounds for CISCO PIX firewall bugs.
       
              smtp_quote_rfc821_envelope (yes)
      -              Quote addresses in Postfix SMTP client MAIL  FROM  and  RCPT  TO
      +              Quote  addresses  in  Postfix  SMTP client MAIL FROM and RCPT TO
                     commands as required by RFC 5321.
       
              smtp_reply_filter (empty)
      -              A  mechanism  to  transform replies from remote SMTP servers one
      +              A mechanism to transform replies from remote  SMTP  servers  one
                     line at a time.
       
              smtp_skip_5xx_greeting (yes)
      @@ -248,68 +258,68 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.0 and earlier:
       
              smtp_skip_4xx_greeting (yes)
      -              Skip SMTP servers that greet with a 4XX status  code  (go  away,
      +              Skip  SMTP  servers  that greet with a 4XX status code (go away,
                     try again later).
       
              Available in Postfix version 2.2 and later:
       
              smtp_discard_ehlo_keyword_address_maps (empty)
      -              Lookup  tables,  indexed by the remote SMTP server address, with
      -              case insensitive lists of EHLO keywords  (pipelining,  starttls,
      +              Lookup tables, indexed by the remote SMTP server  address,  with
      +              case  insensitive  lists of EHLO keywords (pipelining, starttls,
                     auth, etc.) that the Postfix SMTP client will ignore in the EHLO
                     response from a remote SMTP server.
       
              smtp_discard_ehlo_keywords (empty)
      -              A case insensitive list of EHLO keywords (pipelining,  starttls,
      +              A  case insensitive list of EHLO keywords (pipelining, starttls,
                     auth, etc.) that the Postfix SMTP client will ignore in the EHLO
                     response from a remote SMTP server.
       
              smtp_generic_maps (empty)
      -              Optional lookup tables that perform  address  rewriting  in  the
      -              Postfix  SMTP  client,  typically  to  transform a locally valid
      -              address into a globally valid address when sending  mail  across
      +              Optional  lookup  tables  that  perform address rewriting in the
      +              Postfix SMTP client, typically  to  transform  a  locally  valid
      +              address  into  a globally valid address when sending mail across
                     the Internet.
       
              Available in Postfix version 2.2.9 and later:
       
              smtp_cname_overrides_servername (version dependent)
      -              When  the  remote  SMTP  servername  is a DNS CNAME, replace the
      -              servername with the result from CNAME expansion for the  purpose
      -              of  logging,  SASL password lookup, TLS policy decisions, or TLS
      +              When the remote SMTP servername is  a  DNS  CNAME,  replace  the
      +              servername  with the result from CNAME expansion for the purpose
      +              of logging, SASL password lookup, TLS policy decisions,  or  TLS
                     certificate verification.
       
              Available in Postfix version 2.3 and later:
       
              lmtp_discard_lhlo_keyword_address_maps (empty)
      -              Lookup tables, indexed by the remote LMTP server  address,  with
      -              case  insensitive  lists of LHLO keywords (pipelining, starttls,
      +              Lookup  tables,  indexed by the remote LMTP server address, with
      +              case insensitive lists of LHLO keywords  (pipelining,  starttls,
                     auth, etc.) that the Postfix LMTP client will ignore in the LHLO
                     response from a remote LMTP server.
       
              lmtp_discard_lhlo_keywords (empty)
      -              A  case insensitive list of LHLO keywords (pipelining, starttls,
      +              A case insensitive list of LHLO keywords (pipelining,  starttls,
                     auth, etc.) that the Postfix LMTP client will ignore in the LHLO
                     response from a remote LMTP server.
       
              Available in Postfix version 2.4.4 and later:
       
              send_cyrus_sasl_authzid (no)
      -              When  authenticating  to  a  remote SMTP or LMTP server with the
      -              default setting "no", send no SASL authoriZation  ID  (authzid);
      -              send  only  the  SASL authentiCation ID (authcid) plus the auth-
      +              When authenticating to a remote SMTP or  LMTP  server  with  the
      +              default  setting  "no", send no SASL authoriZation ID (authzid);
      +              send only the SASL authentiCation ID (authcid)  plus  the  auth-
                     cid's password.
       
              Available in Postfix version 2.5 and later:
       
              smtp_header_checks (empty)
      -              Restricted header_checks(5) tables for the Postfix SMTP  client.
      +              Restricted  header_checks(5) tables for the Postfix SMTP client.
       
              smtp_mime_header_checks (empty)
      -              Restricted  mime_header_checks(5)  tables  for  the Postfix SMTP
      +              Restricted mime_header_checks(5) tables  for  the  Postfix  SMTP
                     client.
       
              smtp_nested_header_checks (empty)
      -              Restricted nested_header_checks(5) tables for the  Postfix  SMTP
      +              Restricted  nested_header_checks(5)  tables for the Postfix SMTP
                     client.
       
              smtp_body_checks (empty)
      @@ -318,7 +328,7 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.6 and later:
       
              tcp_windowsize (0)
      -              An  optional  workaround for routers that break TCP window scal-
      +              An optional workaround for routers that break TCP  window  scal-
                     ing.
       
              Available in Postfix version 2.8 and later:
      @@ -329,16 +339,16 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.9 - 3.6:
       
              smtp_per_record_deadline (no)
      -              Change the behavior of the smtp_*_timeout time  limits,  from  a
      -              time  limit  per  read  or write system call, to a time limit to
      -              send or receive a complete record (an SMTP  command  line,  SMTP
      -              response  line,  SMTP message content line, or TLS protocol mes-
      +              Change  the  behavior  of the smtp_*_timeout time limits, from a
      +              time limit per read or write system call, to  a  time  limit  to
      +              send  or  receive  a complete record (an SMTP command line, SMTP
      +              response line, SMTP message content line, or TLS  protocol  mes-
                     sage).
       
              Available in Postfix version 2.9 and later:
       
              smtp_send_dummy_mail_auth (no)
      -              Whether or not to append the "AUTH=<>" option to the  MAIL  FROM
      +              Whether  or  not to append the "AUTH=<>" option to the MAIL FROM
                     command in SASL-authenticated SMTP sessions.
       
              Available in Postfix version 2.11 and later:
      @@ -349,7 +359,7 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 3.0 and later:
       
              smtp_delivery_status_filter ($default_delivery_status_filter)
      -              Optional  filter  for  the  smtp(8) delivery agent to change the
      +              Optional filter for the smtp(8) delivery  agent  to  change  the
                     delivery status code or explanatory text of successful or unsuc-
                     cessful deliveries.
       
      @@ -359,38 +369,38 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 3.3 and later:
       
              smtp_balance_inet_protocols (yes)
      -              When  a remote destination resolves to a combination of IPv4 and
      +              When a remote destination resolves to a combination of IPv4  and
                     IPv6 addresses, ensure that the Postfix SMTP client can try both
                     address types before it runs into the smtp_mx_address_limit.
       
              Available in Postfix 3.5 and later:
       
              info_log_address_format (external)
      -              The  email  address  form that will be used in non-debug logging
      +              The email address form that will be used  in  non-debug  logging
                     (info, warning, etc.).
       
              Available in Postfix 3.6 and later:
       
              dnssec_probe (ns:.)
      -              The DNS query type (default: "ns") and DNS query name  (default:
      +              The  DNS query type (default: "ns") and DNS query name (default:
                     ".") that Postfix may use to determine whether DNSSEC validation
                     is available.
       
      -       known_tcp_ports  (lmtp=24,  smtp=25,   smtps=submissions=465,   submis-
      +       known_tcp_ports   (lmtp=24,   smtp=25,  smtps=submissions=465,  submis-
              sion=587)
      -              Optional setting that avoids lookups in  the  services(5)  data-
      +              Optional  setting  that  avoids lookups in the services(5) data-
                     base.
       
              Available in Postfix version 3.7 and later:
       
              smtp_per_request_deadline (no)
      -              Change  the  behavior  of the smtp_*_timeout time limits, from a
      -              time limit per plaintext or TLS read or write call,  to  a  com-
      -              bined  time  limit  for  sending a complete SMTP request and for
      +              Change the behavior of the smtp_*_timeout time  limits,  from  a
      +              time  limit  per  plaintext or TLS read or write call, to a com-
      +              bined time limit for sending a complete  SMTP  request  and  for
                     receiving a complete SMTP response.
       
              smtp_min_data_rate (500)
      -              The minimum plaintext data transfer  rate  in  bytes/second  for
      +              The  minimum  plaintext  data  transfer rate in bytes/second for
                     DATA    requests,    when    deadlines    are    enabled    with
                     smtp_per_request_deadline.
       
      @@ -400,16 +410,16 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 3.8 and later:
       
              use_srv_lookup (empty)
      -              Enables discovery for the specified  service(s)  using  DNS  SRV
      +              Enables  discovery  for  the  specified service(s) using DNS SRV
                     records.
       
              ignore_srv_lookup_error (no)
      -              When  SRV  record  lookup  fails,  fall back to MX or IP address
      +              When SRV record lookup fails, fall back  to  MX  or  IP  address
                     lookup as if SRV record lookup was not enabled.
       
              allow_srv_lookup_fallback (no)
      -              When SRV record lookup fails or no SRV record exists, fall  back
      -              to  MX  or  IP  address  lookup  as if SRV record lookup was not
      +              When  SRV record lookup fails or no SRV record exists, fall back
      +              to MX or IP address lookup as  if  SRV  record  lookup  was  not
                     enabled.
       
       MIME PROCESSING CONTROLS
      @@ -428,7 +438,7 @@ SMTP(8)                                                                SMTP(8)
              Available in Postfix version 2.1 and later:
       
              smtp_send_xforward_command (no)
      -              Send  the  non-standard  XFORWARD  command when the Postfix SMTP
      +              Send the non-standard XFORWARD command  when  the  Postfix  SMTP
                     server EHLO response announces XFORWARD support.
       
       SASL AUTHENTICATION CONTROLS
      @@ -436,60 +446,66 @@ SMTP(8)                                                                SMTP(8)
                     Enable SASL authentication in the Postfix SMTP client.
       
              smtp_sasl_password_maps (empty)
      -              Optional Postfix  SMTP  client  lookup  tables  with  one  user-
      -              name:password  entry  per  sender,  remote  hostname or next-hop
      +              Optional  Postfix  SMTP  client  lookup  tables  with  one user-
      +              name:password entry per  sender,  remote  hostname  or  next-hop
                     domain.
       
              smtp_sasl_security_options (noplaintext, noanonymous)
                     Postfix SMTP client SASL security options; as of Postfix 2.3 the
      -              list  of available features depends on the SASL client implemen-
      +              list of available features depends on the SASL client  implemen-
                     tation that is selected with smtp_sasl_type.
       
              Available in Postfix version 2.2 and later:
       
              smtp_sasl_mechanism_filter (empty)
      -              If non-empty, a Postfix SMTP client filter for the  remote  SMTP
      +              If  non-empty,  a Postfix SMTP client filter for the remote SMTP
                     server's list of offered SASL mechanisms.
       
              Available in Postfix version 2.3 and later:
       
              smtp_sender_dependent_authentication (no)
                     Enable  sender-dependent  authentication  in  the  Postfix  SMTP
      -              client; this is available only  with  SASL  authentication,  and
      -              disables  SMTP  connection caching to ensure that mail from dif-
      +              client;  this  is  available  only with SASL authentication, and
      +              disables SMTP connection caching to ensure that mail  from  dif-
                     ferent senders will use the appropriate credentials.
       
              smtp_sasl_path (empty)
                     Implementation-specific information that the Postfix SMTP client
      -              passes  through  to  the  SASL  plug-in  implementation  that is
      +              passes through  to  the  SASL  plug-in  implementation  that  is
                     selected with smtp_sasl_type.
       
              smtp_sasl_type (cyrus)
      -              The SASL plug-in type that the Postfix SMTP  client  should  use
      +              The  SASL  plug-in  type that the Postfix SMTP client should use
                     for authentication.
       
              Available in Postfix version 2.5 and later:
       
              smtp_sasl_auth_cache_name (empty)
      -              An  optional table to prevent repeated SASL authentication fail-
      -              ures with the same remote SMTP  server  hostname,  username  and
      +              An optional table to prevent repeated SASL authentication  fail-
      +              ures  with  the  same  remote SMTP server hostname, username and
                     password.
       
              smtp_sasl_auth_cache_time (90d)
      -              The  maximal age of an smtp_sasl_auth_cache_name entry before it
      +              The maximal age of an smtp_sasl_auth_cache_name entry before  it
                     is removed.
       
              smtp_sasl_auth_soft_bounce (yes)
      -              When a remote SMTP server rejects a SASL authentication  request
      -              with  a 535 reply code, defer mail delivery instead of returning
      +              When  a remote SMTP server rejects a SASL authentication request
      +              with a 535 reply code, defer mail delivery instead of  returning
                     mail as undeliverable.
       
              Available in Postfix version 2.9 and later:
       
              smtp_send_dummy_mail_auth (no)
      -              Whether or not to append the "AUTH=<>" option to the  MAIL  FROM
      +              Whether  or  not to append the "AUTH=<>" option to the MAIL FROM
                     command in SASL-authenticated SMTP sessions.
       
      +       Available in Postfix version 3.9 and later:
      +
      +       smtp_sasl_password_result_delimiter (:)
      +              The delimiter between username and password in  sasl_passwd_maps
      +              lookup results.
      +
       STARTTLS SUPPORT CONTROLS
              Detailed  information  about STARTTLS configuration may be found in the
              TLS_README document.
      @@ -619,7 +635,7 @@ SMTP(8)                                                                SMTP(8)
       
              Available in Postfix version 2.6 and later:
       
      -       smtp_tls_protocols (see postconf -d output)
      +       smtp_tls_protocols (see 'postconf -d' output)
                     TLS  protocols that the Postfix SMTP client will use with oppor-
                     tunistic TLS encryption.
       
      @@ -724,6 +740,12 @@ SMTP(8)                                                                SMTP(8)
                     The application name passed by Postfix to OpenSSL  library  ini-
                     tialization functions.
       
      +       Available in Postfix version 3.9 and later:
      +
      +       smtp_tls_enable_rpk (no)
      +              Request  that remote SMTP servers send an RFC7250 raw public key
      +              instead of an X.509 certificate.
      +
       OBSOLETE STARTTLS CONTROLS
              The following configuration parameters  exist  for  compatibility  with
              Postfix  versions  before  2.3.  Support for these will be removed in a
      @@ -954,7 +976,7 @@ SMTP(8)                                                                SMTP(8)
                     The  local  network  interface  addresses  that this mail system
                     receives mail on.
       
      -       inet_protocols (see 'postconf -d output')
      +       inet_protocols (see 'postconf -d' output)
                     The Internet protocols Postfix will attempt to use  when  making
                     or accepting connections.
       
      @@ -1119,5 +1141,5 @@ SMTP(8)                                                                SMTP(8)
              Victor Duchovni
              Morgan Stanley
       
      -                                                                       SMTP(8)
      +                                       8                           SMTP,(LMTP)
       
      diff --git a/html/smtpd.8.html b/html/smtpd.8.html index 672302a..85a8aee 100644 --- a/html/smtpd.8.html +++ b/html/smtpd.8.html @@ -560,7 +560,7 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.6 and later: - smtpd_tls_protocols (see postconf -d output) + smtpd_tls_protocols (see 'postconf -d' output) TLS protocols accepted by the Postfix SMTP server with oppor- tunistic TLS encryption. @@ -648,6 +648,13 @@ SMTPD(8) SMTPD(8) The application name passed by Postfix to OpenSSL library ini- tialization functions. + Available in Postfix version 3.9 and later: + + smtpd_tls_enable_rpk (no) + Request that remote SMTP clients send an RFC7250 raw public key + instead of an X.509 certificate, when asking for or requiring + client authentication. + OBSOLETE STARTTLS CONTROLS The following configuration parameters exist for compatibility with Postfix versions before 2.3. Support for these will be removed in a @@ -801,7 +808,7 @@ SMTPD(8) SMTPD(8) receives mail on by way of a proxy or network address transla- tion unit. - inet_protocols (see 'postconf -d output') + inet_protocols (see 'postconf -d' output) The Internet protocols Postfix will attempt to use when making or accepting connections. @@ -840,30 +847,31 @@ SMTPD(8) SMTPD(8) aliased to addresses in other local or remote domains. virtual_alias_maps ($virtual_maps) - Optional lookup tables that alias specific mail addresses or - domains to other local or remote addresses. + Optional lookup tables with aliases that apply to all recipi- + ents: local(8), virtual, and remote; this is unlike alias_maps + that apply only to local(8) recipients. unknown_virtual_alias_reject_code (550) - The Postfix SMTP server reply code when a recipient address - matches $virtual_alias_domains, and $virtual_alias_maps speci- - fies a list of lookup tables that does not match the recipient + The Postfix SMTP server reply code when a recipient address + matches $virtual_alias_domains, and $virtual_alias_maps speci- + fies a list of lookup tables that does not match the recipient address. Parameters concerning known/unknown recipients in virtual mailbox domains: virtual_mailbox_domains ($virtual_mailbox_maps) - Postfix is the final destination for the specified list of - domains; mail is delivered via the $virtual_transport mail + Postfix is the final destination for the specified list of + domains; mail is delivered via the $virtual_transport mail delivery transport. virtual_mailbox_maps (empty) - Optional lookup tables with all valid addresses in the domains + Optional lookup tables with all valid addresses in the domains that match $virtual_mailbox_domains. unknown_virtual_mailbox_reject_code (550) - The Postfix SMTP server reply code when a recipient address - matches $virtual_mailbox_domains, and $virtual_mailbox_maps + The Postfix SMTP server reply code when a recipient address + matches $virtual_mailbox_domains, and $virtual_mailbox_maps specifies a list of lookup tables that does not match the recip- ient address. @@ -872,7 +880,7 @@ SMTPD(8) SMTPD(8) control client request rates. line_length_limit (2048) - Upon input, long lines are chopped up into pieces of at most + Upon input, long lines are chopped up into pieces of at most this length; upon delivery, long lines are reconstructed. queue_minfree (0) @@ -880,62 +888,62 @@ SMTPD(8) SMTPD(8) tem that is needed to receive mail. message_size_limit (10240000) - The maximal size in bytes of a message, including envelope + The maximal size in bytes of a message, including envelope information. smtpd_recipient_limit (1000) - The maximal number of recipients that the Postfix SMTP server + The maximal number of recipients that the Postfix SMTP server accepts per message delivery request. smtpd_timeout (normal: 300s, overload: 10s) - When the Postfix SMTP server wants to send an SMTP server - response, how long the Postfix SMTP server will wait for an - underlying network write operation to complete; and when the - Postfix SMTP server Postfix wants to receive an SMTP client - request, how long the Postfix SMTP server will wait for an + When the Postfix SMTP server wants to send an SMTP server + response, how long the Postfix SMTP server will wait for an + underlying network write operation to complete; and when the + Postfix SMTP server Postfix wants to receive an SMTP client + request, how long the Postfix SMTP server will wait for an underlying network read operation to complete. smtpd_history_flush_threshold (100) - The maximal number of lines in the Postfix SMTP server command - history before it is flushed upon receipt of EHLO, RSET, or end + The maximal number of lines in the Postfix SMTP server command + history before it is flushed upon receipt of EHLO, RSET, or end of DATA. Available in Postfix version 2.3 and later: smtpd_peername_lookup (yes) - Attempt to look up the remote SMTP client hostname, and verify + Attempt to look up the remote SMTP client hostname, and verify that the name matches the client IP address. The per SMTP client connection count and request rate limits are imple- - mented in co-operation with the anvil(8) service, and are available in + mented in co-operation with the anvil(8) service, and are available in Postfix version 2.2 and later. smtpd_client_connection_count_limit (50) - How many simultaneous connections any client is allowed to make + How many simultaneous connections any client is allowed to make to this service. smtpd_client_connection_rate_limit (0) - The maximal number of connection attempts any client is allowed + The maximal number of connection attempts any client is allowed to make to this service per time unit. smtpd_client_message_rate_limit (0) - The maximal number of message delivery requests that any client - is allowed to make to this service per time unit, regardless of + The maximal number of message delivery requests that any client + is allowed to make to this service per time unit, regardless of whether or not Postfix actually accepts those messages. smtpd_client_recipient_rate_limit (0) - The maximal number of recipient addresses that any client is - allowed to send to this service per time unit, regardless of + The maximal number of recipient addresses that any client is + allowed to send to this service per time unit, regardless of whether or not Postfix actually accepts those recipients. smtpd_client_event_limit_exceptions ($mynetworks) - Clients that are excluded from smtpd_client_*_count/rate_limit + Clients that are excluded from smtpd_client_*_count/rate_limit restrictions. Available in Postfix version 2.3 and later: smtpd_client_new_tls_session_rate_limit (0) - The maximal number of new (i.e., uncached) TLS sessions that a + The maximal number of new (i.e., uncached) TLS sessions that a remote SMTP client is allowed to negotiate with this service per time unit. @@ -943,29 +951,29 @@ SMTPD(8) SMTPD(8) smtpd_per_record_deadline (normal: no, overload: yes) Change the behavior of the smtpd_timeout and smtpd_start- - tls_timeout time limits, from a time limit per read or write - system call, to a time limit to send or receive a complete - record (an SMTP command line, SMTP response line, SMTP message + tls_timeout time limits, from a time limit per read or write + system call, to a time limit to send or receive a complete + record (an SMTP command line, SMTP response line, SMTP message content line, or TLS protocol message). Available in Postfix version 3.1 and later: smtpd_client_auth_rate_limit (0) - The maximal number of AUTH commands that any client is allowed - to send to this service per time unit, regardless of whether or + The maximal number of AUTH commands that any client is allowed + to send to this service per time unit, regardless of whether or not Postfix actually accepts those commands. Available in Postfix version 3.7 and later: smtpd_per_request_deadline (normal: no, overload: yes) Change the behavior of the smtpd_timeout and smtpd_start- - tls_timeout time limits, from a time limit per plaintext or TLS - read or write call, to a combined time limit for receiving a - complete SMTP request and for sending a complete SMTP response. + tls_timeout time limits, from a time limit per plaintext or TLS + read or write call, to a combined time limit for receiving a + complete SMTP request and for sending a complete SMTP response. smtpd_min_data_rate (500) - The minimum plaintext data transfer rate in bytes/second for - DATA and BDAT requests, when deadlines are enabled with + The minimum plaintext data transfer rate in bytes/second for + DATA and BDAT requests, when deadlines are enabled with smtpd_per_request_deadline. header_from_format (standard) @@ -974,27 +982,27 @@ SMTPD(8) SMTPD(8) Available in Postfix version 3.8 and later: smtpd_client_ipv4_prefix_length (32) - Aggregate smtpd_client_*_count and smtpd_client_*_rate statis- + Aggregate smtpd_client_*_count and smtpd_client_*_rate statis- tics by IPv4 network blocks with the specified network prefix. smtpd_client_ipv6_prefix_length (84) - Aggregate smtpd_client_*_count and smtpd_client_*_rate statis- + Aggregate smtpd_client_*_count and smtpd_client_*_rate statis- tics by IPv6 network blocks with the specified network prefix. Available in Postfix 3.9, 3.8.1, 3.7.6, 3.6.10, 3.5.20 and later: smtpd_forbid_unauth_pipelining (Postfix >= 3.9: yes) - Disconnect remote SMTP clients that violate RFC 2920 (or 5321) + Disconnect remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: - smtpd_forbid_bare_newline (Postfix < 3.9: no) - Reject or restrict input lines from an SMTP client that end in + smtpd_forbid_bare_newline (Postfix >= 3.9: normalize) + Reject or restrict input lines from an SMTP client that end in <LF> instead of the standard <CR><LF>. smtpd_forbid_bare_newline_exclusions ($mynetworks) - Exclude the specified clients from smtpd_forbid_bare_newline + Exclude the specified clients from smtpd_forbid_bare_newline enforcement. Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and later: @@ -1004,55 +1012,55 @@ SMTPD(8) SMTPD(8) request with "smtpd_forbid_bare_newline = reject". TARPIT CONTROLS - When a remote SMTP client makes errors, the Postfix SMTP server can - insert delays before responding. This can help to slow down run-away - software. The behavior is controlled by an error counter that counts + When a remote SMTP client makes errors, the Postfix SMTP server can + insert delays before responding. This can help to slow down run-away + software. The behavior is controlled by an error counter that counts the number of errors within an SMTP session that a client makes without delivering mail. smtpd_error_sleep_time (1s) - With Postfix version 2.1 and later: the SMTP server response - delay after a client has made more than $smtpd_soft_error_limit - errors, and fewer than $smtpd_hard_error_limit errors, without + With Postfix version 2.1 and later: the SMTP server response + delay after a client has made more than $smtpd_soft_error_limit + errors, and fewer than $smtpd_hard_error_limit errors, without delivering mail. smtpd_soft_error_limit (10) - The number of errors a remote SMTP client is allowed to make - without delivering mail before the Postfix SMTP server slows + The number of errors a remote SMTP client is allowed to make + without delivering mail before the Postfix SMTP server slows down all its responses. smtpd_hard_error_limit (normal: 20, overload: 1) - The maximal number of errors a remote SMTP client is allowed to + The maximal number of errors a remote SMTP client is allowed to make without delivering mail. smtpd_junk_command_limit (normal: 100, overload: 1) - The number of junk commands (NOOP, VRFY, ETRN or RSET) that a - remote SMTP client can send before the Postfix SMTP server + The number of junk commands (NOOP, VRFY, ETRN or RSET) that a + remote SMTP client can send before the Postfix SMTP server starts to increment the error counter with each junk command. Available in Postfix version 2.1 and later: smtpd_recipient_overshoot_limit (1000) - The number of recipients that a remote SMTP client can send in + The number of recipients that a remote SMTP client can send in excess of the limit specified with $smtpd_recipient_limit, - before the Postfix SMTP server increments the per-session error + before the Postfix SMTP server increments the per-session error count for each excess recipient. ACCESS POLICY DELEGATION CONTROLS - As of version 2.1, Postfix can be configured to delegate access policy - decisions to an external server that runs outside Postfix. See the + As of version 2.1, Postfix can be configured to delegate access policy + decisions to an external server that runs outside Postfix. See the file SMTPD_POLICY_README for more information. smtpd_policy_service_max_idle (300s) - The time after which an idle SMTPD policy service connection is + The time after which an idle SMTPD policy service connection is closed. smtpd_policy_service_max_ttl (1000s) - The time after which an active SMTPD policy service connection + The time after which an active SMTPD policy service connection is closed. smtpd_policy_service_timeout (100s) - The time limit for connecting to, writing to, or receiving from + The time limit for connecting to, writing to, or receiving from a delegated SMTPD policy server. Available in Postfix version 3.0 and later: @@ -1062,81 +1070,81 @@ SMTPD(8) SMTPD(8) The default action when an SMTPD policy service request fails. smtpd_policy_service_request_limit (0) - The maximal number of requests per SMTPD policy service connec- + The maximal number of requests per SMTPD policy service connec- tion, or zero (no limit). smtpd_policy_service_try_limit (2) - The maximal number of attempts to send an SMTPD policy service + The maximal number of attempts to send an SMTPD policy service request before giving up. smtpd_policy_service_retry_delay (1s) - The delay between attempts to resend a failed SMTPD policy ser- + The delay between attempts to resend a failed SMTPD policy ser- vice request. Available in Postfix version 3.1 and later: smtpd_policy_service_policy_context (empty) - Optional information that the Postfix SMTP server specifies in - the "policy_context" attribute of a policy service request - (originally, to share the same service endpoint among multiple + Optional information that the Postfix SMTP server specifies in + the "policy_context" attribute of a policy service request + (originally, to share the same service endpoint among multiple check_policy_service clients). ACCESS CONTROLS - The SMTPD_ACCESS_README document gives an introduction to all the SMTP + The SMTPD_ACCESS_README document gives an introduction to all the SMTP server access control features. smtpd_delay_reject (yes) - Wait until the RCPT TO command before evaluating + Wait until the RCPT TO command before evaluating $smtpd_client_restrictions, $smtpd_helo_restrictions and $smtpd_sender_restrictions, or wait until the ETRN command - before evaluating $smtpd_client_restrictions and + before evaluating $smtpd_client_restrictions and $smtpd_helo_restrictions. parent_domain_matches_subdomains (see 'postconf -d' output) - A list of Postfix features where the pattern "example.com" also - matches subdomains of example.com, instead of requiring an + A list of Postfix features where the pattern "example.com" also + matches subdomains of example.com, instead of requiring an explicit ".example.com" pattern. smtpd_client_restrictions (empty) - Optional restrictions that the Postfix SMTP server applies in + Optional restrictions that the Postfix SMTP server applies in the context of a client connection request. smtpd_helo_required (no) - Require that a remote SMTP client introduces itself with the - HELO or EHLO command before sending the MAIL command or other + Require that a remote SMTP client introduces itself with the + HELO or EHLO command before sending the MAIL command or other commands that require EHLO negotiation. smtpd_helo_restrictions (empty) - Optional restrictions that the Postfix SMTP server applies in + Optional restrictions that the Postfix SMTP server applies in the context of a client HELO command. smtpd_sender_restrictions (empty) - Optional restrictions that the Postfix SMTP server applies in + Optional restrictions that the Postfix SMTP server applies in the context of a client MAIL FROM command. smtpd_recipient_restrictions (see 'postconf -d' output) - Optional restrictions that the Postfix SMTP server applies in - the context of a client RCPT TO command, after + Optional restrictions that the Postfix SMTP server applies in + the context of a client RCPT TO command, after smtpd_relay_restrictions. smtpd_etrn_restrictions (empty) - Optional restrictions that the Postfix SMTP server applies in + Optional restrictions that the Postfix SMTP server applies in the context of a client ETRN command. allow_untrusted_routing (no) - Forward mail with sender-specified routing - (user[@%!]remote[@%!]site) from untrusted clients to destina- + Forward mail with sender-specified routing + (user[@%!]remote[@%!]site) from untrusted clients to destina- tions matching $relay_domains. smtpd_restriction_classes (empty) User-defined aliases for groups of access restrictions. smtpd_null_access_lookup_key (<>) - The lookup key to be used in SMTP access(5) tables instead of + The lookup key to be used in SMTP access(5) tables instead of the null sender address. permit_mx_backup_networks (empty) - Restrict the use of the permit_mx_backup SMTP access feature to + Restrict the use of the permit_mx_backup SMTP access feature to only domains whose primary MX hosts match the listed networks. Available in Postfix version 2.0 and later: @@ -1146,19 +1154,19 @@ SMTPD(8) SMTPD(8) applies in the context of the SMTP DATA command. smtpd_expansion_filter (see 'postconf -d' output) - What characters are allowed in $name expansions of RBL reply + What characters are allowed in $name expansions of RBL reply templates. Available in Postfix version 2.1 and later: smtpd_reject_unlisted_sender (no) - Request that the Postfix SMTP server rejects mail from unknown - sender addresses, even when no explicit reject_unlisted_sender + Request that the Postfix SMTP server rejects mail from unknown + sender addresses, even when no explicit reject_unlisted_sender access restriction is specified. smtpd_reject_unlisted_recipient (yes) - Request that the Postfix SMTP server rejects mail for unknown - recipient addresses, even when no explicit + Request that the Postfix SMTP server rejects mail for unknown + recipient addresses, even when no explicit reject_unlisted_recipient access restriction is specified. Available in Postfix version 2.2 and later: @@ -1172,17 +1180,17 @@ SMTPD(8) SMTPD(8) smtpd_relay_restrictions (permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination) Access restrictions for mail relay control that the Postfix SMTP - server applies in the context of the RCPT TO command, before + server applies in the context of the RCPT TO command, before smtpd_recipient_restrictions. SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS - Postfix version 2.1 introduces sender and recipient address verifica- + Postfix version 2.1 introduces sender and recipient address verifica- tion. This feature is implemented by sending probe email messages that are not actually delivered. This feature is requested via the - reject_unverified_sender and reject_unverified_recipient access - restrictions. The status of verification probes is maintained by the - verify(8) server. See the file ADDRESS_VERIFICATION_README for infor- - mation about how to configure and operate the Postfix sender/recipient + reject_unverified_sender and reject_unverified_recipient access + restrictions. The status of verification probes is maintained by the + verify(8) server. See the file ADDRESS_VERIFICATION_README for infor- + mation about how to configure and operate the Postfix sender/recipient address verification service. address_verify_poll_count (normal: 3, overload: 1) @@ -1194,7 +1202,7 @@ SMTPD(8) SMTPD(8) fication request in progress. address_verify_sender ($double_bounce_sender) - The sender address to use in address verification probes; prior + The sender address to use in address verification probes; prior to Postfix 2.5 the default was "postmaster". unverified_sender_reject_code (450) @@ -1202,18 +1210,18 @@ SMTPD(8) SMTPD(8) address is rejected by the reject_unverified_sender restriction. unverified_recipient_reject_code (450) - The numerical Postfix SMTP server response when a recipient - address is rejected by the reject_unverified_recipient restric- + The numerical Postfix SMTP server response when a recipient + address is rejected by the reject_unverified_recipient restric- tion. Available in Postfix version 2.6 and later: unverified_sender_defer_code (450) - The numerical Postfix SMTP server response code when a sender + The numerical Postfix SMTP server response code when a sender address probe fails due to a temporary error condition. unverified_recipient_defer_code (450) - The numerical Postfix SMTP server response when a recipient + The numerical Postfix SMTP server response when a recipient address probe fails due to a temporary error condition. unverified_sender_reject_reason (empty) @@ -1225,17 +1233,17 @@ SMTPD(8) SMTPD(8) reject_unverified_recipient. unverified_sender_tempfail_action ($reject_tempfail_action) - The Postfix SMTP server's action when reject_unverified_sender + The Postfix SMTP server's action when reject_unverified_sender fails due to a temporary error condition. unverified_recipient_tempfail_action ($reject_tempfail_action) - The Postfix SMTP server's action when reject_unverified_recipi- + The Postfix SMTP server's action when reject_unverified_recipi- ent fails due to a temporary error condition. Available with Postfix 2.9 and later: address_verify_sender_ttl (0s) - The time between changes in the time-dependent portion of + The time between changes in the time-dependent portion of address verification probe sender addresses. ACCESS CONTROL RESPONSES @@ -1247,36 +1255,36 @@ SMTPD(8) SMTPD(8) map "reject" action. defer_code (450) - The numerical Postfix SMTP server response code when a remote + The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by the "defer" restriction. invalid_hostname_reject_code (501) - The numerical Postfix SMTP server response code when the client - HELO or EHLO command parameter is rejected by the + The numerical Postfix SMTP server response code when the client + HELO or EHLO command parameter is rejected by the reject_invalid_helo_hostname restriction. maps_rbl_reject_code (554) - The numerical Postfix SMTP server response code when a remote - SMTP client request is blocked by the reject_rbl_client, + The numerical Postfix SMTP server response code when a remote + SMTP client request is blocked by the reject_rbl_client, reject_rhsbl_client, reject_rhsbl_reverse_client, reject_rhsbl_sender or reject_rhsbl_recipient restriction. non_fqdn_reject_code (504) - The numerical Postfix SMTP server reply code when a client - request is rejected by the reject_non_fqdn_helo_hostname, + The numerical Postfix SMTP server reply code when a client + request is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender or reject_non_fqdn_recipient restriction. plaintext_reject_code (450) - The numerical Postfix SMTP server response code when a request + The numerical Postfix SMTP server response code when a request is rejected by the reject_plaintext_session restriction. reject_code (554) - The numerical Postfix SMTP server response code when a remote + The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by the "reject" restriction. relay_domains_reject_code (554) - The numerical Postfix SMTP server response code when a client - request is rejected by the reject_unauth_destination recipient + The numerical Postfix SMTP server response code when a client + request is rejected by the reject_unauth_destination recipient restriction. unknown_address_reject_code (450) @@ -1284,24 +1292,24 @@ SMTPD(8) SMTPD(8) a sender or recipient address because its domain is unknown. unknown_client_reject_code (450) - The numerical Postfix SMTP server response code when a client - without valid address <=> name mapping is rejected by the + The numerical Postfix SMTP server response code when a client + without valid address <=> name mapping is rejected by the reject_unknown_client_hostname restriction. unknown_hostname_reject_code (450) - The numerical Postfix SMTP server response code when the host- - name specified with the HELO or EHLO command is rejected by the + The numerical Postfix SMTP server response code when the host- + name specified with the HELO or EHLO command is rejected by the reject_unknown_helo_hostname restriction. Available in Postfix version 2.0 and later: default_rbl_reply (see 'postconf -d' output) - The default Postfix SMTP server response template for a request + The default Postfix SMTP server response template for a request that is rejected by an RBL-based restriction. multi_recipient_bounce_reject_code (550) - The numerical Postfix SMTP server response code when a remote - SMTP client request is blocked by the reject_multi_recipi- + The numerical Postfix SMTP server response code when a remote + SMTP client request is blocked by the reject_multi_recipi- ent_bounce restriction. rbl_reply_maps (empty) @@ -1311,52 +1319,52 @@ SMTPD(8) SMTPD(8) access_map_defer_code (450) The numerical Postfix SMTP server response code for an access(5) - map "defer" action, including "defer_if_permit" or + map "defer" action, including "defer_if_permit" or "defer_if_reject". reject_tempfail_action (defer_if_permit) - The Postfix SMTP server's action when a reject-type restriction + The Postfix SMTP server's action when a reject-type restriction fails due to a temporary error condition. unknown_helo_hostname_tempfail_action ($reject_tempfail_action) - The Postfix SMTP server's action when reject_unknown_helo_host- + The Postfix SMTP server's action when reject_unknown_helo_host- name fails due to a temporary error condition. unknown_address_tempfail_action ($reject_tempfail_action) - The Postfix SMTP server's action when - reject_unknown_sender_domain or reject_unknown_recipient_domain + The Postfix SMTP server's action when + reject_unknown_sender_domain or reject_unknown_recipient_domain fail due to a temporary error condition. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to handle a + How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. command_directory (see 'postconf -d' output) The location of all postfix administrative commands. double_bounce_sender (double-bounce) - The sender address of postmaster notifications that are gener- + The sender address of postmaster notifications that are gener- ated by the mail system. ipc_timeout (3600s) - The time limit for sending or receiving information over an + The time limit for sending or receiving information over an internal communication channel. mail_name (Postfix) - The mail system name that is displayed in Received: headers, in + The mail system name that is displayed in Received: headers, in the SMTP greeting banner, and in bounced mail. mail_owner (postfix) - The UNIX system account that owns the Postfix queue and most + The UNIX system account that owns the Postfix queue and most Postfix daemon processes. max_idle (100s) - The maximum amount of time that an idle Postfix daemon process + The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. max_use (100) @@ -1367,11 +1375,11 @@ SMTPD(8) SMTPD(8) The internet hostname of this mail system. mynetworks (see 'postconf -d' output) - The list of "trusted" remote SMTP clients that have more privi- + The list of "trusted" remote SMTP clients that have more privi- leges than "strangers". myorigin ($myhostname) - The domain name that locally-posted mail appears to come from, + The domain name that locally-posted mail appears to come from, and that locally posted mail is delivered to. process_id (read-only) @@ -1384,24 +1392,24 @@ SMTPD(8) SMTPD(8) The location of the Postfix top-level queue directory. recipient_delimiter (empty) - The set of characters that can separate an email address local- + The set of characters that can separate an email address local- part, user name, or a .forward file name from its extension. smtpd_banner ($myhostname ESMTP $mail_name) - The text that follows the 220 status code in the SMTP greeting + The text that follows the 220 status code in the SMTP greeting banner. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix version 2.2 and later: smtpd_forbidden_commands (CONNECT GET POST regexp:{{/^[^A-Z]/ Bogus}}) - List of commands that cause the Postfix SMTP server to immedi- + List of commands that cause the Postfix SMTP server to immedi- ately terminate the session with a 221 code. Available in Postfix version 2.5 and later: @@ -1418,7 +1426,7 @@ SMTPD(8) SMTPD(8) Available in Postfix 3.4 and later: smtpd_reject_footer_maps (empty) - Lookup tables, indexed by the complete Postfix SMTP server 4xx + Lookup tables, indexed by the complete Postfix SMTP server 4xx or 5xx response, with reject footer templates. SEE ALSO diff --git a/html/socketmap_table.5.html b/html/socketmap_table.5.html index a8bbd07..4c9e96c 100644 --- a/html/socketmap_table.5.html +++ b/html/socketmap_table.5.html @@ -18,7 +18,7 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5) postmap -q - socketmap:unix:pathname:name <inputfile DESCRIPTION - The Postfix mail system uses optional tables for address rewriting. + The Postfix mail system uses optional tables for address rewriting, mail routing or policy lookup. The Postfix socketmap client expects TCP endpoint names of the form diff --git a/html/tlsproxy.8.html b/html/tlsproxy.8.html index 0c36743..615a222 100644 --- a/html/tlsproxy.8.html +++ b/html/tlsproxy.8.html @@ -170,26 +170,26 @@ TLSPROXY(8) TLSPROXY(8) tialization functions. STARTTLS SERVER CONTROLS - These settings are clones of Postfix SMTP server settings. They allow + These settings are clones of Postfix SMTP server settings. They allow tlsproxy(8) to load the same certificate and private key information as - the Postfix SMTP server, before dropping privileges, so that the key - files can be kept read-only for root. These settings can currently not - be overruled by information in a tlsproxy(8) client request, but that + the Postfix SMTP server, before dropping privileges, so that the key + files can be kept read-only for root. These settings can currently not + be overruled by information in a tlsproxy(8) client request, but that limitation may be removed in a future version. tlsproxy_tls_CAfile ($smtpd_tls_CAfile) - A file containing (PEM format) CA certificates of root CAs + A file containing (PEM format) CA certificates of root CAs trusted to sign either remote SMTP client certificates or inter- mediate CA certificates. tlsproxy_tls_CApath ($smtpd_tls_CApath) - A directory containing (PEM format) CA certificates of root CAs + A directory containing (PEM format) CA certificates of root CAs trusted to sign either remote SMTP client certificates or inter- mediate CA certificates. tlsproxy_tls_always_issue_session_ids ($smtpd_tls_always_issue_ses- sion_ids) - Force the Postfix tlsproxy(8) server to issue a TLS session id, + Force the Postfix tlsproxy(8) server to issue a TLS session id, even when TLS session caching is turned off. tlsproxy_tls_ask_ccert ($smtpd_tls_ask_ccert) @@ -199,7 +199,7 @@ TLSPROXY(8) TLSPROXY(8) The verification depth for remote SMTP client certificates. tlsproxy_tls_cert_file ($smtpd_tls_cert_file) - File with the Postfix tlsproxy(8) server RSA certificate in PEM + File with the Postfix tlsproxy(8) server RSA certificate in PEM format. tlsproxy_tls_ciphers ($smtpd_tls_ciphers) @@ -207,47 +207,47 @@ TLSPROXY(8) TLSPROXY(8) will use with opportunistic TLS encryption. tlsproxy_tls_dcert_file ($smtpd_tls_dcert_file) - File with the Postfix tlsproxy(8) server DSA certificate in PEM + File with the Postfix tlsproxy(8) server DSA certificate in PEM format. tlsproxy_tls_dh1024_param_file ($smtpd_tls_dh1024_param_file) - File with DH parameters that the Postfix tlsproxy(8) server + File with DH parameters that the Postfix tlsproxy(8) server should use with non-export EDH ciphers. tlsproxy_tls_dh512_param_file ($smtpd_tls_dh512_param_file) - File with DH parameters that the Postfix tlsproxy(8) server + File with DH parameters that the Postfix tlsproxy(8) server should use with export-grade EDH ciphers. tlsproxy_tls_dkey_file ($smtpd_tls_dkey_file) - File with the Postfix tlsproxy(8) server DSA private key in PEM + File with the Postfix tlsproxy(8) server DSA private key in PEM format. tlsproxy_tls_eccert_file ($smtpd_tls_eccert_file) - File with the Postfix tlsproxy(8) server ECDSA certificate in + File with the Postfix tlsproxy(8) server ECDSA certificate in PEM format. tlsproxy_tls_eckey_file ($smtpd_tls_eckey_file) - File with the Postfix tlsproxy(8) server ECDSA private key in + File with the Postfix tlsproxy(8) server ECDSA private key in PEM format. tlsproxy_tls_eecdh_grade ($smtpd_tls_eecdh_grade) - The Postfix tlsproxy(8) server security grade for ephemeral + The Postfix tlsproxy(8) server security grade for ephemeral elliptic-curve Diffie-Hellman (EECDH) key exchange. tlsproxy_tls_exclude_ciphers ($smtpd_tls_exclude_ciphers) - List of ciphers or cipher types to exclude from the tlsproxy(8) + List of ciphers or cipher types to exclude from the tlsproxy(8) server cipher list at all TLS security levels. tlsproxy_tls_fingerprint_digest ($smtpd_tls_fingerprint_digest) - The message digest algorithm to construct remote SMTP + The message digest algorithm to construct remote SMTP client-certificate fingerprints. tlsproxy_tls_key_file ($smtpd_tls_key_file) - File with the Postfix tlsproxy(8) server RSA private key in PEM + File with the Postfix tlsproxy(8) server RSA private key in PEM format. tlsproxy_tls_loglevel ($smtpd_tls_loglevel) - Enable additional Postfix tlsproxy(8) server logging of TLS + Enable additional Postfix tlsproxy(8) server logging of TLS activity. tlsproxy_tls_mandatory_ciphers ($smtpd_tls_mandatory_ciphers) @@ -256,7 +256,7 @@ TLSPROXY(8) TLSPROXY(8) tlsproxy_tls_mandatory_exclude_ciphers ($smtpd_tls_manda- tory_exclude_ciphers) - Additional list of ciphers or cipher types to exclude from the + Additional list of ciphers or cipher types to exclude from the tlsproxy(8) server cipher list at mandatory TLS security levels. tlsproxy_tls_mandatory_protocols ($smtpd_tls_mandatory_protocols) @@ -264,67 +264,74 @@ TLSPROXY(8) TLSPROXY(8) with mandatory TLS encryption. tlsproxy_tls_protocols ($smtpd_tls_protocols) - List of TLS protocols that the Postfix tlsproxy(8) server will + List of TLS protocols that the Postfix tlsproxy(8) server will exclude or include with opportunistic TLS encryption. tlsproxy_tls_req_ccert ($smtpd_tls_req_ccert) - With mandatory TLS encryption, require a trusted remote SMTP + With mandatory TLS encryption, require a trusted remote SMTP client certificate in order to allow TLS connections to proceed. tlsproxy_tls_security_level ($smtpd_tls_security_level) - The SMTP TLS security level for the Postfix tlsproxy(8) server; + The SMTP TLS security level for the Postfix tlsproxy(8) server; when a non-empty value is specified, this overrides the obsolete parameters smtpd_use_tls and smtpd_enforce_tls. tlsproxy_tls_chain_files ($smtpd_tls_chain_files) - Files with the Postfix tlsproxy(8) server keys and certificate + Files with the Postfix tlsproxy(8) server keys and certificate chains in PEM format. + Available in Postfix version 3.9 and later: + + tlsproxy_tls_enable_rpk ($smtpd_tls_enable_rpk) + Request that remote SMTP clients send an RFC7250 raw public key + instead of an X.509 certificate, when asking or requiring client + authentication. + STARTTLS CLIENT CONTROLS - These settings are clones of Postfix SMTP client settings. They allow + These settings are clones of Postfix SMTP client settings. They allow tlsproxy(8) to load the same certificate and private key information as - the Postfix SMTP client, before dropping privileges, so that the key + the Postfix SMTP client, before dropping privileges, so that the key files can be kept read-only for root. Some settings may be overruled by information in a tlsproxy(8) client request. Available in Postfix version 3.4 and later: tlsproxy_client_CAfile ($smtp_tls_CAfile) - A file containing CA certificates of root CAs trusted to sign - either remote TLS server certificates or intermediate CA cer- + A file containing CA certificates of root CAs trusted to sign + either remote TLS server certificates or intermediate CA cer- tificates. tlsproxy_client_CApath ($smtp_tls_CApath) - Directory with PEM format Certification Authority certificates - that the Postfix tlsproxy(8) client uses to verify a remote TLS + Directory with PEM format Certification Authority certificates + that the Postfix tlsproxy(8) client uses to verify a remote TLS server certificate. tlsproxy_client_chain_files ($smtp_tls_chain_files) - Files with the Postfix tlsproxy(8) client keys and certificate + Files with the Postfix tlsproxy(8) client keys and certificate chains in PEM format. tlsproxy_client_cert_file ($smtp_tls_cert_file) - File with the Postfix tlsproxy(8) client RSA certificate in PEM + File with the Postfix tlsproxy(8) client RSA certificate in PEM format. tlsproxy_client_key_file ($smtp_tls_key_file) - File with the Postfix tlsproxy(8) client RSA private key in PEM + File with the Postfix tlsproxy(8) client RSA private key in PEM format. tlsproxy_client_dcert_file ($smtp_tls_dcert_file) - File with the Postfix tlsproxy(8) client DSA certificate in PEM + File with the Postfix tlsproxy(8) client DSA certificate in PEM format. tlsproxy_client_dkey_file ($smtp_tls_dkey_file) - File with the Postfix tlsproxy(8) client DSA private key in PEM + File with the Postfix tlsproxy(8) client DSA private key in PEM format. tlsproxy_client_eccert_file ($smtp_tls_eccert_file) - File with the Postfix tlsproxy(8) client ECDSA certificate in + File with the Postfix tlsproxy(8) client ECDSA certificate in PEM format. tlsproxy_client_eckey_file ($smtp_tls_eckey_file) - File with the Postfix tlsproxy(8) client ECDSA private key in + File with the Postfix tlsproxy(8) client ECDSA private key in PEM format. tlsproxy_client_fingerprint_digest ($smtp_tls_fingerprint_digest) @@ -332,7 +339,7 @@ TLSPROXY(8) TLSPROXY(8) certificate fingerprints. tlsproxy_client_loglevel ($smtp_tls_loglevel) - Enable additional Postfix tlsproxy(8) client logging of TLS + Enable additional Postfix tlsproxy(8) client logging of TLS activity. tlsproxy_client_loglevel_parameter (smtp_tls_loglevel) @@ -343,43 +350,43 @@ TLSPROXY(8) TLSPROXY(8) The verification depth for remote TLS server certificates. tlsproxy_client_use_tls ($smtp_use_tls) - Opportunistic mode: use TLS when a remote server announces TLS + Opportunistic mode: use TLS when a remote server announces TLS support. tlsproxy_client_enforce_tls ($smtp_enforce_tls) - Enforcement mode: require that SMTP servers use TLS encryption. + Enforcement mode: require that SMTP servers use TLS encryption. tlsproxy_client_per_site ($smtp_tls_per_site) - Optional lookup tables with the Postfix tlsproxy(8) client TLS - usage policy by next-hop destination and by remote TLS server + Optional lookup tables with the Postfix tlsproxy(8) client TLS + usage policy by next-hop destination and by remote TLS server hostname. Available in Postfix version 3.4-3.6: tlsproxy_client_level ($smtp_tls_security_level) - The default TLS security level for the Postfix tlsproxy(8) + The default TLS security level for the Postfix tlsproxy(8) client. tlsproxy_client_policy ($smtp_tls_policy_maps) - Optional lookup tables with the Postfix tlsproxy(8) client TLS + Optional lookup tables with the Postfix tlsproxy(8) client TLS security policy by next-hop destination. Available in Postfix version 3.7 and later: tlsproxy_client_security_level ($smtp_tls_security_level) - The default TLS security level for the Postfix tlsproxy(8) + The default TLS security level for the Postfix tlsproxy(8) client. tlsproxy_client_policy_maps ($smtp_tls_policy_maps) - Optional lookup tables with the Postfix tlsproxy(8) client TLS + Optional lookup tables with the Postfix tlsproxy(8) client TLS security policy by next-hop destination. OBSOLETE STARTTLS SUPPORT CONTROLS - These parameters are supported for compatibility with smtpd(8) legacy + These parameters are supported for compatibility with smtpd(8) legacy parameters. tlsproxy_use_tls ($smtpd_use_tls) - Opportunistic TLS: announce STARTTLS support to remote SMTP + Opportunistic TLS: announce STARTTLS support to remote SMTP clients, but do not require that clients use TLS encryption. tlsproxy_enforce_tls ($smtpd_enforce_tls) @@ -387,11 +394,11 @@ TLSPROXY(8) TLSPROXY(8) and require that clients use TLS encryption. tlsproxy_client_use_tls ($smtp_use_tls) - Opportunistic mode: use TLS when a remote server announces TLS + Opportunistic mode: use TLS when a remote server announces TLS support. tlsproxy_client_enforce_tls ($smtp_enforce_tls) - Enforcement mode: require that SMTP servers use TLS encryption. + Enforcement mode: require that SMTP servers use TLS encryption. RESOURCE CONTROLS tlsproxy_watchdog_timeout (10s) @@ -400,7 +407,7 @@ TLSPROXY(8) TLSPROXY(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. process_id (read-only) @@ -413,7 +420,7 @@ TLSPROXY(8) TLSPROXY(8) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix 3.3 and later: diff --git a/html/trivial-rewrite.8.html b/html/trivial-rewrite.8.html index 1bcd8e7..7b1e3e3 100644 --- a/html/trivial-rewrite.8.html +++ b/html/trivial-rewrite.8.html @@ -134,9 +134,11 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) Available in Postfix 2.2 and later: remote_header_rewrite_domain (empty) - Don't rewrite message headers from remote clients at all when - this parameter is empty; otherwise, rewrite message headers and - append the specified domain name to incomplete addresses. + Rewrite or add message headers in mail from remote clients if + the remote_header_rewrite_domain parameter value is non-empty, + updating incomplete addresses with the domain specified in the + remote_header_rewrite_domain parameter, and adding missing head- + ers. ROUTING CONTROLS The following is applicable to Postfix version 2.0 and later. Earlier @@ -155,13 +157,14 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) relay_transport (relay) The default mail delivery transport and next-hop destination for - remote delivery to domains listed with $relay_domains. + the relay domain address class: recipient domains that match + $relay_domains. default_transport (smtp) The default mail delivery transport and next-hop destination for - destinations that do not match $mydestination, $inet_interfaces, - $proxy_interfaces, $virtual_alias_domains, $virtual_mail- - box_domains, or $relay_domains. + the default domain class: recipient domains that do not match + $mydestination, $inet_interfaces, $proxy_interfaces, $vir- + tual_alias_domains, $virtual_mailbox_domains, or $relay_domains. parent_domain_matches_subdomains (see 'postconf -d' output) A list of Postfix features where the pattern "example.com" also @@ -169,8 +172,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) explicit ".example.com" pattern. relayhost (empty) - The next-hop destination(s) for non-local mail; overrides - non-local domains in recipient addresses. + The next-hop destination(s) for non-local mail; takes precedence + over non-local domains in recipient addresses. transport_maps (empty) Optional lookup tables with mappings from recipient address to diff --git a/html/virtual.5.html b/html/virtual.5.html index 7e9061e..c1c6ece 100644 --- a/html/virtual.5.html +++ b/html/virtual.5.html @@ -18,101 +18,102 @@ VIRTUAL(5) VIRTUAL(5) postmap -q - /etc/postfix/virtual <inputfile DESCRIPTION - The optional virtual(5) alias table rewrites recipient addresses for - all local, all virtual, and all remote mail destinations. This is - unlike the aliases(5) table which is used only for local(8) delivery. - This feature is implemented in the Postfix cleanup(8) daemon before - mail is queued. + The optional virtual(5) alias table (virtual_alias_maps) applies to all + recipients: local(8), virtual, and remote. This feature is implemented + in the Postfix cleanup(8) daemon before mail is queued. - Virtual aliasing is recursive; to terminate recursion for a specific + This is unlike the aliases(5) table (alias_maps) which applies only to + local(8) recipients. + + Virtual aliasing is recursive; to terminate recursion for a specific address, alias that address to itself. - The main applications of virtual aliasing are: + The main applications of virtual aliasing are: o To redirect mail for one address to one or more addresses. - o To implement virtual alias domains where all addresses are + o To implement virtual alias domains where all addresses are aliased to addresses in other domains. - Virtual alias domains are not to be confused with the virtual + Virtual alias domains are not to be confused with the virtual mailbox domains that are implemented with the Postfix virtual(8) - mail delivery agent. With virtual mailbox domains, each recipi- + mail delivery agent. With virtual mailbox domains, each recipi- ent address can have its own mailbox. - Virtual aliasing is applied only to recipient envelope addresses, and - does not affect message headers. Use canonical(5) mapping to rewrite + Virtual aliasing is applied only to recipient envelope addresses, and + does not affect message headers. Use canonical(5) mapping to rewrite header and envelope addresses in general. - Normally, the virtual(5) alias table is specified as a text file that + Normally, the virtual(5) alias table is specified as a text file that serves as input to the postmap(1) command. The result, an indexed file - in dbm or db format, is used for fast searching by the mail system. + in dbm or db format, is used for fast searching by the mail system. Execute the command "postmap /etc/postfix/virtual" to rebuild an indexed file after changing the corresponding text file. - When the table is provided via other means such as NIS, LDAP or SQL, + When the table is provided via other means such as NIS, LDAP or SQL, the same lookups are done as for ordinary indexed files. - Alternatively, the table can be provided as a regular-expression map - where patterns are given as regular expressions, or lookups can be - directed to a TCP-based server. In those case, the lookups are done in - a slightly different way as described below under "REGULAR EXPRESSION + Alternatively, the table can be provided as a regular-expression map + where patterns are given as regular expressions, or lookups can be + directed to a TCP-based server. In those case, the lookups are done in + a slightly different way as described below under "REGULAR EXPRESSION TABLES" or "TCP-BASED TABLES". CASE FOLDING - The search string is folded to lowercase before database lookup. As of - Postfix 2.3, the search string is not case folded with database types - such as regexp: or pcre: whose lookup fields can match both upper and + The search string is folded to lowercase before database lookup. As of + Postfix 2.3, the search string is not case folded with database types + such as regexp: or pcre: whose lookup fields can match both upper and lower case. TABLE FORMAT The input format for the postmap(1) command is as follows: pattern address, address, ... - When pattern matches a mail address, replace it by the corre- + When pattern matches a mail address, replace it by the corre- sponding address. blank lines and comments - Empty lines and whitespace-only lines are ignored, as are lines + Empty lines and whitespace-only lines are ignored, as are lines whose first non-whitespace character is a `#'. multi-line text - A logical line starts with non-whitespace text. A line that + A logical line starts with non-whitespace text. A line that starts with whitespace continues a logical line. TABLE SEARCH ORDER - With lookups from indexed files such as DB or DBM, or from networked - tables such as NIS, LDAP or SQL, each user@domain query produces a + With lookups from indexed files such as DB or DBM, or from networked + tables such as NIS, LDAP or SQL, each user@domain query produces a sequence of query patterns as described below. Each query pattern is sent to each specified lookup table before trying the next query pattern, until a match is found. user@domain address, address, ... - Redirect mail for user@domain to address. This form has the + Redirect mail for user@domain to address. This form has the highest precedence. user address, address, ... - Redirect mail for user@site to address when site is equal to - $myorigin, when site is listed in $mydestination, or when it is + Redirect mail for user@site to address when site is equal to + $myorigin, when site is listed in $mydestination, or when it is listed in $inet_interfaces or $proxy_interfaces. - This functionality overlaps with the functionality of the local - aliases(5) database. The difference is that virtual(5) mapping + This functionality overlaps with the functionality of the local + aliases(5) database. The difference is that virtual(5) mapping can be applied to non-local addresses. @domain address, address, ... - Redirect mail for other users in domain to address. This form + Redirect mail for other users in domain to address. This form has the lowest precedence. - Note: @domain is a wild-card. With this form, the Postfix SMTP - server accepts mail for any recipient in domain, regardless of - whether that recipient exists. This may turn your mail system - into a backscatter source: Postfix first accepts mail for - non-existent recipients and then tries to return that mail as + Note: @domain is a wild-card. With this form, the Postfix SMTP + server accepts mail for any recipient in domain, regardless of + whether that recipient exists. This may turn your mail system + into a backscatter source: Postfix first accepts mail for + non-existent recipients and then tries to return that mail as "undeliverable" to the often forged sender address. - To avoid backscatter with mail for a wild-card domain, replace - the wild-card mapping with explicit 1:1 mappings, or add a + To avoid backscatter with mail for a wild-card domain, replace + the wild-card mapping with explicit 1:1 mappings, or add a reject_unverified_recipient restriction for that domain: smtpd_recipient_restrictions = @@ -128,11 +129,11 @@ VIRTUAL(5) VIRTUAL(5) RESULT ADDRESS REWRITING The lookup result is subject to address rewriting: - o When the result has the form @otherdomain, the result becomes - the same user in otherdomain. This works only for the first + o When the result has the form @otherdomain, the result becomes + the same user in otherdomain. This works only for the first address in a multi-address lookup result. - o When "append_at_myorigin=yes", append "@$myorigin" to addresses + o When "append_at_myorigin=yes", append "@$myorigin" to addresses without "@domain". o When "append_dot_mydomain=yes", append ".$mydomain" to addresses @@ -140,26 +141,26 @@ VIRTUAL(5) VIRTUAL(5) ADDRESS EXTENSION When a mail address localpart contains the optional recipient delimiter - (e.g., user+foo@domain), the lookup order becomes: user+foo@domain, + (e.g., user+foo@domain), the lookup order becomes: user+foo@domain, user@domain, user+foo, user, and @domain. - The propagate_unmatched_extensions parameter controls whether an + The propagate_unmatched_extensions parameter controls whether an unmatched address extension (+foo) is propagated to the result of a ta- ble lookup. VIRTUAL ALIAS DOMAINS - Besides virtual aliases, the virtual alias table can also be used to - implement virtual alias domains. With a virtual alias domain, all + Besides virtual aliases, the virtual alias table can also be used to + implement virtual alias domains. With a virtual alias domain, all recipient addresses are aliased to addresses in other domains. - Virtual alias domains are not to be confused with the virtual mailbox - domains that are implemented with the Postfix virtual(8) mail delivery - agent. With virtual mailbox domains, each recipient address can have + Virtual alias domains are not to be confused with the virtual mailbox + domains that are implemented with the Postfix virtual(8) mail delivery + agent. With virtual mailbox domains, each recipient address can have its own mailbox. - With a virtual alias domain, the virtual domain has its own user name - space. Local (i.e. non-virtual) usernames are not visible in a virtual - alias domain. In particular, local aliases(5) and local mailing lists + With a virtual alias domain, the virtual domain has its own user name + space. Local (i.e. non-virtual) usernames are not visible in a virtual + alias domain. In particular, local aliases(5) and local mailing lists are not visible as localname@virtual-alias.domain. Support for a virtual alias domain looks like: @@ -167,7 +168,7 @@ VIRTUAL(5) VIRTUAL(5) /etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual - Note: some systems use dbm databases instead of hash. See the output + Note: some systems use dbm databases instead of hash. See the output from "postconf -m" for available database types. /etc/postfix/virtual: @@ -177,46 +178,46 @@ VIRTUAL(5) VIRTUAL(5) user2@virtual-alias.domain address2, address3 The virtual-alias.domain anything entry is required for a virtual alias - domain. Without this entry, mail is rejected with "relay access + domain. Without this entry, mail is rejected with "relay access denied", or bounces with "mail loops back to myself". - Do not specify virtual alias domain names in the main.cf mydestination + Do not specify virtual alias domain names in the main.cf mydestination or relay_domains configuration parameters. - With a virtual alias domain, the Postfix SMTP server accepts mail for + With a virtual alias domain, the Postfix SMTP server accepts mail for known-user@virtual-alias.domain, and rejects mail for unknown-user@vir- tual-alias.domain as undeliverable. - Instead of specifying the virtual alias domain name via the vir- - tual_alias_maps table, you may also specify it via the main.cf vir- + Instead of specifying the virtual alias domain name via the vir- + tual_alias_maps table, you may also specify it via the main.cf vir- tual_alias_domains configuration parameter. This latter parameter uses the same syntax as the main.cf mydestination configuration parameter. REGULAR EXPRESSION TABLES - This section describes how the table lookups change when the table is - given in the form of regular expressions. For a description of regular + This section describes how the table lookups change when the table is + given in the form of regular expressions. For a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to the entire - address being looked up. Thus, user@domain mail addresses are not bro- - ken up into their user and @domain constituent parts, nor is user+foo + Each pattern is a regular expression that is applied to the entire + address being looked up. Thus, user@domain mail addresses are not bro- + ken up into their user and @domain constituent parts, nor is user+foo broken up into user and foo. - Patterns are applied in the order as specified in the table, until a + Patterns are applied in the order as specified in the table, until a pattern is found that matches the search string. - Results are the same as with indexed file lookups, with the additional - feature that parenthesized substrings from the pattern can be interpo- + Results are the same as with indexed file lookups, with the additional + feature that parenthesized substrings from the pattern can be interpo- lated as $1, $2 and so on. TCP-BASED TABLES - This section describes how the table lookups change when lookups are - directed to a TCP-based server. For a description of the TCP - client/server lookup protocol, see tcp_table(5). This feature is + This section describes how the table lookups change when lookups are + directed to a TCP-based server. For a description of the TCP + client/server lookup protocol, see tcp_table(5). This feature is available in Postfix 2.5 and later. - Each lookup operation uses the entire address once. Thus, user@domain - mail addresses are not broken up into their user and @domain con- + Each lookup operation uses the entire address once. Thus, user@domain + mail addresses are not broken up into their user and @domain con- stituent parts, nor is user+foo broken up into user and foo. Results are the same as with indexed file lookups. @@ -230,8 +231,9 @@ VIRTUAL(5) VIRTUAL(5) Use the "postfix reload" command after a configuration change. virtual_alias_maps ($virtual_maps) - Optional lookup tables that alias specific mail addresses or - domains to other local or remote addresses. + Optional lookup tables with aliases that apply to all recipi- + ents: local(8), virtual, and remote; this is unlike alias_maps + that apply only to local(8) recipients. virtual_alias_domains ($virtual_alias_maps) Postfix is the final destination for the specified list of vir- @@ -245,8 +247,8 @@ VIRTUAL(5) VIRTUAL(5) Other parameters of interest: inet_interfaces (all) - The network interface addresses that this mail system receives - mail on. + The local network interface addresses that this mail system + receives mail on. mydestination ($myhostname, localhost.$mydomain, localhost) The list of domains that are delivered via the $local_transport @@ -263,8 +265,9 @@ VIRTUAL(5) VIRTUAL(5) set to "-". proxy_interfaces (empty) - The network interface addresses that this mail system receives - mail on by way of a proxy or network address translation unit. + The remote network interface addresses that this mail system + receives mail on by way of a proxy or network address transla- + tion unit. SEE ALSO cleanup(8), canonicalize and enqueue mail diff --git a/makedefs b/makedefs index 005e4b3..1932e36 100644 --- a/makedefs +++ b/makedefs @@ -35,6 +35,7 @@ # Specifies one or more non-default object libraries. Postfix # 3.0 and later specify some of their database library # dependencies with AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB, +# AUXLIBS_MONGODB, # AUXLIBS_MYSQL, AUXLIBS_PCRE, AUXLIBS_PGSQL, AUXLIBS_SDBM, # and AUXLIBS_SQLITE, respectively. # .IP \fBCC=\fIcompiler_command\fR @@ -184,6 +185,9 @@ # New York, NY 10011, USA #-- +# Override all LC_* settings and LANG for reproducibility. +LC_ALL=C; export LC_ALL + # By now all shells must have functions. error() { @@ -1242,7 +1246,7 @@ DEFINED_MAP_TYPES=` # Propagate AUXLIBS_FOO or merge them into global AUXLIBS (i.e. SYSLIBS). -PLUGGABLE_MAPS="CDB LDAP LMDB MYSQL PCRE PGSQL SDBM SQLITE" +PLUGGABLE_MAPS="CDB LDAP LMDB MONGODB MYSQL PCRE PGSQL SDBM SQLITE" case "$dynamicmaps" in yes) for name in $PLUGGABLE_MAPS diff --git a/man/Makefile.in b/man/Makefile.in index f98402c..40a5236 100644 --- a/man/Makefile.in +++ b/man/Makefile.in @@ -17,7 +17,7 @@ CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \ man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \ man5/cidr_table.5 man5/tcp_table.5 man5/header_checks.5 \ man5/body_checks.5 man5/ldap_table.5 man5/lmdb_table.5 \ - man5/memcache_table.5 man5/mysql_table.5 \ + man5/memcache_table.5 man5/mongodb_table.5 man5/mysql_table.5 \ man5/pgsql_table.5 man5/master.5 man5/nisplus_table.5 \ man5/generic.5 man5/bounce.5 man5/postfix-wrapper.5 \ man5/sqlite_table.5 man5/socketmap_table.5 @@ -316,6 +316,11 @@ man5/memcache_table.5: ../proto/memcache_table (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman - $? >$@ +man5/mongodb_table.5: ../proto/mongodb_table + ../mantools/fixman ../proto/postconf.proto $? >junk && \ + (cmp -s junk $? || mv junk $?) && rm -f junk + ../mantools/srctoman - $? >$@ + man5/mysql_table.5: ../proto/mysql_table ../mantools/fixman ../proto/postconf.proto $? >junk && \ (cmp -s junk $? || mv junk $?) && rm -f junk diff --git a/man/man1/makedefs.1 b/man/man1/makedefs.1 index 70c848e..c921ac2 100644 --- a/man/man1/makedefs.1 +++ b/man/man1/makedefs.1 @@ -38,6 +38,7 @@ of the make(1) command. Specifies one or more non\-default object libraries. Postfix 3.0 and later specify some of their database library dependencies with AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB, +AUXLIBS_MONGODB, AUXLIBS_MYSQL, AUXLIBS_PCRE, AUXLIBS_PGSQL, AUXLIBS_SDBM, and AUXLIBS_SQLITE, respectively. .IP \fBCC=\fIcompiler_command\fR diff --git a/man/man1/postcat.1 b/man/man1/postcat.1 index eb3025b..f6541eb 100644 --- a/man/man1/postcat.1 +++ b/man/man1/postcat.1 @@ -88,7 +88,7 @@ The text below provides only a parameter summary. See The default location of the Postfix main.cf and master.cf configuration files. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a privileged Postfix +The list of environment variables that a privileged Postfix process will import from a non\-Postfix parent process, or name=value environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/man/man1/postconf.1 b/man/man1/postconf.1 index e422429..4121806 100644 --- a/man/man1/postconf.1 +++ b/man/man1/postconf.1 @@ -12,7 +12,7 @@ Postfix configuration utility .ti -4 \fBManaging main.cf:\fR -\fBpostconf\fR [\fB\-dfhHnopvx\fR] [\fB\-c \fIconfig_dir\fR] +\fBpostconf\fR [\fB\-dfhHnopqvx\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-C \fIclass,...\fR] [\fIparameter ...\fR] \fBpostconf\fR [\fB\-epv\fR] [\fB\-c \fIconfig_dir\fR] @@ -27,7 +27,7 @@ Postfix configuration utility .ti -4 \fBManaging master.cf service entries:\fR -\fBpostconf\fR \fB\-M\fR [\fB\-fovx\fR] [\fB\-c \fIconfig_dir\fR] +\fBpostconf\fR \fB\-M\fR [\fB\-foqvx\fR] [\fB\-c \fIconfig_dir\fR] [\fIservice\fR[\fB/\fItype\fR]\fI ...\fR] \fBpostconf\fR \fB\-M\fR [\fB\-ev\fR] [\fB\-c \fIconfig_dir\fR] @@ -42,7 +42,7 @@ Postfix configuration utility .ti -4 \fBManaging master.cf service fields:\fR -\fBpostconf\fR \fB\-F\fR [\fB\-fhHovx\fR] [\fB\-c \fIconfig_dir\fR] +\fBpostconf\fR \fB\-F\fR [\fB\-fhHoqvx\fR] [\fB\-c \fIconfig_dir\fR] [\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR] \fBpostconf\fR \fB\-F\fR [\fB\-ev\fR] [\fB\-c \fIconfig_dir\fR] @@ -51,7 +51,7 @@ Postfix configuration utility .ti -4 \fBManaging master.cf service parameters:\fR -\fBpostconf\fR \fB\-P\fR [\fB\-fhHovx\fR] [\fB\-c \fIconfig_dir\fR] +\fBpostconf\fR \fB\-P\fR [\fB\-fhHoqvx\fR] [\fB\-c \fIconfig_dir\fR] [\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR] \fBpostconf\fR \fB\-P\fR [\fB\-ev\fR] [\fB\-c \fIconfig_dir\fR] @@ -299,6 +299,11 @@ Memcache database client. This is described in \fBmemcache_table\fR(5). This feature is available with Postfix 2.9 and later. +.IP "\fBmongodb\fR" +MongoDB database client. This is described in +\fBmongodb_table\fR(5). + +This feature is available with Postfix 3.9 and later. .IP "\fBmysql\fR (read\-only)" MySQL database client. Available on systems with support for MySQL databases. This is described in \fBmysql_table\fR(5). @@ -458,6 +463,10 @@ service type fields that are omitted will be handled as "*" wildcard fields. This feature is available with Postfix 2.11 and later. +.IP \fB\-q\fR +Do not log warnings for deprecated or unused parameters. + +This feature is available with Postfix 3.9 and later. .IP "\fB\-t\fR [\fItemplate_file\fR]" Display the templates for text that appears at the beginning of delivery status notification (DSN) messages, without diff --git a/man/man1/postdrop.1 b/man/man1/postdrop.1 index 23d6012..9dffd68 100644 --- a/man/man1/postdrop.1 +++ b/man/man1/postdrop.1 @@ -78,7 +78,7 @@ environment parameter. The default location of the Postfix main.cf and master.cf configuration files. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a privileged Postfix +The list of environment variables that a privileged Postfix process will import from a non\-Postfix parent process, or name=value environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/man/man1/postfix.1 b/man/man1/postfix.1 index c3ad0d8..da39dc5 100644 --- a/man/man1/postfix.1 +++ b/man/man1/postfix.1 @@ -317,7 +317,7 @@ postfix\-wrapper(5), Postfix multi\-instance API Table\-driven mechanisms: access(5), Postfix SMTP access control table -aliases(5), Postfix alias database +aliases(5), Postfix local aliasing canonical(5), Postfix input address rewriting generic(5), Postfix output address rewriting header_checks(5), body_checks(5), Postfix content inspection @@ -330,6 +330,7 @@ cidr_table(5), Associate CIDR pattern with value ldap_table(5), Postfix LDAP client lmdb_table(5), Postfix LMDB database driver memcache_table(5), Postfix memcache client +mongodb_table(5), Postfix MongoDB client mysql_table(5), Postfix MYSQL client nisplus_table(5), Postfix NIS+ client pcre_table(5), Associate PCRE pattern with value diff --git a/man/man1/postkick.1 b/man/man1/postkick.1 index 6cd0ef6..779a353 100644 --- a/man/man1/postkick.1 +++ b/man/man1/postkick.1 @@ -66,7 +66,7 @@ configuration files. How long the \fBpostkick\fR(1) command waits for a request to enter the Postfix daemon process input buffer before giving up. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a privileged Postfix +The list of environment variables that a privileged Postfix process will import from a non\-Postfix parent process, or name=value environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/man/man1/postlock.1 b/man/man1/postlock.1 index cd468e7..6c07319 100644 --- a/man/man1/postlock.1 +++ b/man/man1/postlock.1 @@ -99,7 +99,7 @@ The delay between attempts to fork() a child process. The default location of the Postfix main.cf and master.cf configuration files. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a privileged Postfix +The list of environment variables that a privileged Postfix process will import from a non\-Postfix parent process, or name=value environment overrides. .SH "SEE ALSO" diff --git a/man/man1/postlog.1 b/man/man1/postlog.1 index 52bd815..d9723e7 100644 --- a/man/man1/postlog.1 +++ b/man/man1/postlog.1 @@ -94,6 +94,12 @@ The name of an optional logfile that is written by the Postfix \fBpostlogd\fR(8) service. .IP "\fBpostlog_service_name (postlog)\fR" The name of the \fBpostlogd\fR(8) service entry in master.cf. +.PP +Available in Postfix 3.9 and later: +.IP "\fBmaillog_file_permissions (0600)\fR" +The file access permissions that will be set when the file +$maillog_file is created for the first time, or when the file is +created after an existing file is rotated. .SH "SEE ALSO" .na .nf diff --git a/man/man1/postsuper.1 b/man/man1/postsuper.1 index 885330f..8c5da03 100644 --- a/man/man1/postsuper.1 +++ b/man/man1/postsuper.1 @@ -46,7 +46,7 @@ from standard input. For example, to delete all mail with exactly one recipient \fBuser@example.com\fR: .sp .nf -postqueue \-j | jq -r ' +postqueue \-j | jq \-r ' # See JSON OBJECT FORMAT section in the postqueue(1) manpage select(.recipients[0].address == "user@example.com") | select(.recipients[1].address == null) @@ -54,7 +54,7 @@ postqueue \-j | jq -r ' ' | postsuper \-d \- .fi .sp -(note the "jq -r" option), or the historical form: +(note the "jq \-r" option), or the historical form: .sp .nf mailq | tail \-n +2 | grep \-v '^ *(' | awk 'BEGIN { RS = "" } @@ -302,7 +302,7 @@ the hash_queue_names parameter. The names of queue directories that are split across multiple subdirectory levels. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a privileged Postfix +The list of environment variables that a privileged Postfix process will import from a non\-Postfix parent process, or name=value environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/man/man1/posttls-finger.1 b/man/man1/posttls-finger.1 index 1e22a03..3cba972 100644 --- a/man/man1/posttls-finger.1 +++ b/man/man1/posttls-finger.1 @@ -109,7 +109,7 @@ fingerprints (with DANE TLSA records the algorithm is specified in the DNS). In Postfix versions prior to 3.6, the default value was "md5". .IP "\fB\-f\fR" -Lookup the associated DANE TLSA RRset even when a hostname is not an +Look up the associated DANE TLSA RRset even when a hostname is not an alias and its address records lie in an unsigned zone. See smtp_tls_force_insecure_host_tlsa_lookup for details. .IP "\fB\-F \fICAfile.pem\fR (default: none)" @@ -270,6 +270,15 @@ is typically provided on port 465 by servers that are compatible with the SMTP\-in\-SSL protocol, rather than the STARTTLS protocol. The destination \fIdomain\fR:\fIport\fR must of course provide such a service. +.IP "\fB\-x\fR" +Prefer RFC7250 non\-X.509 raw public key (RPK) server credentials. By +default only X.509 certificates are accepted. This is analogous to +setting \fBsmtp_tls_enable_rpk = yes\fR in the smtp(8) client. At the +fingerprint security level, when raw public keys are enabled, only +public key (and not certificate) fingerprints will be compared against +the specified list of \fImatch\fR arguments. Certificate fingerprints +are fragile when raw public keys are solicited, the server may at some +point in time start returning only the public key. .IP "\fB\-X\fR" Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode, for program development only. diff --git a/man/man1/sendmail.1 b/man/man1/sendmail.1 index 22affe6..e3bc7a6 100644 --- a/man/man1/sendmail.1 +++ b/man/man1/sendmail.1 @@ -440,9 +440,10 @@ daemon processes. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top\-level queue directory. .IP "\fBremote_header_rewrite_domain (empty)\fR" -Don't rewrite message headers from remote clients at all when -this parameter is empty; otherwise, rewrite message headers and -append the specified domain name to incomplete addresses. +Rewrite or add message headers in mail from remote clients if +the remote_header_rewrite_domain parameter value is non\-empty, +updating incomplete addresses with the domain specified in the +remote_header_rewrite_domain parameter, and adding missing headers. .IP "\fBsyslog_facility (mail)\fR" The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" diff --git a/man/man1/smtp-source.1 b/man/man1/smtp-source.1 index 014ee10..238bc28 100644 --- a/man/man1/smtp-source.1 +++ b/man/man1/smtp-source.1 @@ -48,7 +48,7 @@ when the listen queue is full. Don't disconnect after sending a message; send the next message over the same connection. .IP "\fB\-f \fIfrom\fR" -Use the specified sender address (default: ). +Use the specified sender address (default: ). .IP "\fB\-F \fIfile\fR" Send the pre\-formatted message header and body in the specified \fIfile\fR, while prepending '.' before lines that @@ -60,31 +60,49 @@ include message headers. Speak LMTP rather than SMTP. .IP "\fB\-m \fImessage_count\fR" Send the specified number of messages (default: 1). -.IP "\fB\-M \fImyhostname\fR" +.IP "\fB\-M \fImy\-hostname\fR" Use the specified hostname or [address] in the HELO command and in the default sender and recipient addresses, instead of the machine hostname. .IP "\fB\-N\fR" -Prepend a non\-repeating sequence number to each recipient -address. This avoids the artificial 100% hit rate in the -resolve and rewrite client caches and exercises the -trivial\-rewrite daemon, better approximating Postfix -performance under real\-life work\-loads. +Generate each recipient address by appending a number (a +per\-process recipient counter) to the recipient address +localpart specified with the \fB\-t\fR option. + +Note: to use the number as an address extension, specify +an explicit address delimiter at the end of the recipient +localpart, as in "\fB\-t localpart+@domain\fR" or "\fB\-t +localpart+\fR", where "\fB+\fR" is a Postfix recipient +address delimiter. + +Benefits: +.RS +.IP \(bu +A non\-constant recipient address avoids an unrealistic 100% +cache hit rate in clients of the Postfix trivial\-rewrite +service, better approximating performance under real\-life +work\-loads. +.IP \(bu +A fixed recipient address local\-part with a non\-constant +address extension avoids the need to configure a large +number of valid recipient addresses in the receiving Postfix +server. +.RE .IP \fB\-o\fR Old mode: don't send HELO, and don't send message headers. .IP "\fB\-r \fIrecipient_count\fR" -Send the specified number of recipients per transaction (default: 1). -Recipient names are generated by prepending a number to the -recipient address. +Send the specified number of recipients per transaction +(default: 1), and generate recipient addresses as described +under the \fB\-N\fR option. .IP "\fB\-R \fIinterval\fR" -Wait for a random period of time 0 <= n <= interval between messages. +Wait a random time (0 <= n <= \fIinterval\fR) between messages. Suspending one thread does not affect other delivery threads. .IP "\fB\-s \fIsession_count\fR" Run the specified number of SMTP sessions in parallel (default: 1). .IP "\fB\-S \fIsubject\fR" Send mail with the named subject line (default: none). .IP "\fB\-t \fIto\fR" -Use the specified recipient address (default: ). +Use the specified recipient address (default: ). .IP "\fB\-T \fIwindowsize\fR" Override the default TCP window size. To work around broken TCP window scaling implementations, specify a diff --git a/man/man5/access.5 b/man/man5/access.5 index 07725be..e2eb677 100644 --- a/man/man5/access.5 +++ b/man/man5/access.5 @@ -62,7 +62,7 @@ are lines whose first non\-whitespace character is a `#'. .IP "multi\-line text" A logical line starts with non\-whitespace text. A line that starts with whitespace continues a logical line. -.SH "EMAIL ADDRESS PATTERNS" +.SH "EMAIL ADDRESS PATTERNS IN INDEXED TABLES" .na .nf .ad @@ -99,7 +99,7 @@ When a mail address localpart contains the optional recipient delimiter (e.g., \fIuser+foo\fR@\fIdomain\fR), the lookup order becomes: \fIuser+foo\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR, \fIdomain\fR, \fIuser+foo\fR@, and \fIuser\fR@. -.SH "HOST NAME/ADDRESS PATTERNS" +.SH "HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES" .na .nf .ad diff --git a/man/man5/aliases.5 b/man/man5/aliases.5 index a5da906..ed6a10f 100644 --- a/man/man5/aliases.5 +++ b/man/man5/aliases.5 @@ -13,9 +13,13 @@ Postfix local alias database format .SH DESCRIPTION .ad .fi -The \fBaliases\fR(5) table provides a system\-wide mechanism to -redirect mail for local recipients. The redirections are -processed by the Postfix \fBlocal\fR(8) delivery agent. +The optional \fBaliases\fR(5) table (alias_maps) redirects +mail for local recipients. The redirections are processed +by the Postfix \fBlocal\fR(8) delivery agent. + +This is unlike \fBvirtual\fR(5) aliasing (virtual_alias_maps) +which applies to all recipients: local(8), virtual, and remote, +and which is implemented by the \fBcleanup\fR(8) daemon. Normally, the \fBaliases\fR(5) table is specified as a text file that serves as input to the \fBpostalias\fR(1) command. The @@ -165,7 +169,9 @@ The text below provides only a parameter summary. See The alias databases for \fBlocal\fR(8) delivery that are updated with "\fBnewaliases\fR" or with "\fBsendmail \-bi\fR". .IP "\fBalias_maps (see 'postconf -d' output)\fR" -The alias databases that are used for \fBlocal\fR(8) delivery. +Optional lookup tables with aliases that apply only to \fBlocal\fR(8) +recipients; this is unlike virtual_alias_maps that apply to all +recipients: \fBlocal\fR(8), virtual, and remote. .IP "\fBallow_mail_to_commands (alias, forward)\fR" Restrict \fBlocal\fR(8) mail delivery to external commands. .IP "\fBallow_mail_to_files (alias, forward)\fR" diff --git a/man/man5/canonical.5 b/man/man5/canonical.5 index e987664..8776f3b 100644 --- a/man/man5/canonical.5 +++ b/man/man5/canonical.5 @@ -231,17 +231,14 @@ key to the lookup result. .PP Other parameters of interest: .IP "\fBinet_interfaces (all)\fR" -The network interface addresses that this mail system receives -mail on. +The local network interface addresses that this mail system +receives mail on. .IP "\fBlocal_header_rewrite_clients (permit_inet_interfaces)\fR" -Rewrite message header addresses in mail from these clients and -update incomplete addresses with the domain name in $myorigin or -$mydomain; either don't rewrite message headers from other clients -at all, or rewrite message headers and update incomplete addresses -with the domain specified in the remote_header_rewrite_domain -parameter. +Rewrite or add message headers in mail from these clients, +updating incomplete addresses with the domain name in $myorigin or +$mydomain, and adding missing headers. .IP "\fBproxy_interfaces (empty)\fR" -The network interface addresses that this mail system receives mail +The remote network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit. .IP "\fBmasquerade_classes (envelope_sender, header_sender, header_recipient)\fR" What addresses are subject to address masquerading. @@ -263,9 +260,10 @@ Enable special treatment for owner\-\fIlistname\fR entries in the \fIlistname\fR\-request address localparts when the recipient_delimiter is set to "\-". .IP "\fBremote_header_rewrite_domain (empty)\fR" -Don't rewrite message headers from remote clients at all when -this parameter is empty; otherwise, rewrite message headers and -append the specified domain name to incomplete addresses. +Rewrite or add message headers in mail from remote clients if +the remote_header_rewrite_domain parameter value is non\-empty, +updating incomplete addresses with the domain specified in the +remote_header_rewrite_domain parameter, and adding missing headers. .SH "SEE ALSO" .na .nf diff --git a/man/man5/generic.5 b/man/man5/generic.5 index 6e891eb..b474530 100644 --- a/man/man5/generic.5 +++ b/man/man5/generic.5 @@ -214,10 +214,10 @@ key to the lookup result. .PP Other parameters of interest: .IP "\fBinet_interfaces (all)\fR" -The network interface addresses that this mail system receives -mail on. +The local network interface addresses that this mail system +receives mail on. .IP "\fBproxy_interfaces (empty)\fR" -The network interface addresses that this mail system receives mail +The remote network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit. .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" The list of domains that are delivered via the $local_transport diff --git a/man/man5/header_checks.5 b/man/man5/header_checks.5 index 31ac7dc..92c1de9 100644 --- a/man/man5/header_checks.5 +++ b/man/man5/header_checks.5 @@ -417,34 +417,24 @@ be examined before they are deleted. Examples are: \fBBcc:\fR, .nf .ad .fi -.IP \fBbody_checks\fR -Lookup tables with content filter rules for message body lines. -These filters see one physical line at a time, in chunks of -at most \fB$line_length_limit\fR bytes. -.IP \fBbody_checks_size_limit\fP -The amount of content per message body segment (attachment) that is -subjected to \fB$body_checks\fR filtering. -.IP \fBheader_checks\fR -.IP "\fBmime_header_checks\fR (default: \fB$header_checks\fR)" -.IP "\fBnested_header_checks\fR (default: \fB$header_checks\fR)" -Lookup tables with content filter rules for message header lines: -respectively, these are applied to the initial message headers -(not including MIME headers), to the MIME headers anywhere in -the message, and to the initial headers of attached messages. -.sp -Note: these filters see one logical message header at a time, even -when a message header spans multiple lines. Message headers that -are longer than \fB$header_size_limit\fR characters are truncated. -.IP \fBdisable_mime_input_processing\fR -While receiving mail, give no special treatment to MIME related -message headers; all text after the initial message headers is -considered to be part of the message body. This means that -\fBheader_checks\fR is applied to all the initial message headers, -and that \fBbody_checks\fR is applied to the remainder of the -message. -.sp -Note: when used in this manner, \fBbody_checks\fR will process -a multi\-line message header one line at a time. +.IP "\fBbody_checks (empty)\fR" +Optional lookup tables for content inspection as specified in +the \fBbody_checks\fR(5) manual page. +.IP "\fBbody_checks_size_limit (51200)\fR" +How much text in a message body segment (or attachment, if you +prefer to use that term) is subjected to body_checks inspection. +.IP "\fBheader_checks (empty)\fR" +Optional lookup tables for content inspection of primary non\-MIME +message headers, as specified in the \fBheader_checks\fR(5) manual page. +.IP "\fBmime_header_checks ($header_checks)\fR" +Optional lookup tables for content inspection of MIME related +message headers, as described in the \fBheader_checks\fR(5) manual page. +.IP "\fBnested_header_checks ($header_checks)\fR" +Optional lookup tables for content inspection of non\-MIME message +headers in attached messages, as described in the \fBheader_checks\fR(5) +manual page. +.IP "\fBdisable_mime_input_processing (no)\fR" +Turn off MIME processing while receiving mail. .SH "EXAMPLES" .na .nf diff --git a/man/man5/master.5 b/man/man5/master.5 index 48fd4fd..469ccdf 100644 --- a/man/man5/master.5 +++ b/man/man5/master.5 @@ -225,10 +225,16 @@ personalities via master.cf. .IP \fB\-v\fR Increase the verbose logging level. Specify multiple \fB\-v\fR options to make a Postfix daemon process increasingly verbose. -.IP "Other command\-line arguments" +.IP "\fBCommand\-line arguments that start with {\fR" +With Postfix 3.0 and later specify "{" and "}" around command +arguments that start with "{". The outer "{" and "}" are +removed from the input, together with any leading or trailing +whitespace. +.IP "\fBOther command\-line arguments\fR" Specify "{" and "}" around command arguments that contain -whitespace (Postfix 3.0 and later). Whitespace -after "{" and before "}" is ignored. +whitespace (Postfix 3.0 and later). The outer "{" and "}" +are removed from the input, together with any leading or +trailing whitespace. .SH "SEE ALSO" .na .nf diff --git a/man/man5/mongodb_table.5 b/man/man5/mongodb_table.5 new file mode 100644 index 0000000..cfbedf3 --- /dev/null +++ b/man/man5/mongodb_table.5 @@ -0,0 +1,259 @@ +.TH MONGODB_TABLE 5 +.ad +.fi +.SH NAME +mongodb_table +\- +Postfix MongoDB client configuration +.SH "SYNOPSIS" +.na +.nf +\fBpostmap \-q "\fIstring\fB" mongodb:/etc/postfix/\fIfilename\fR + +\fBpostmap \-q \- mongodb:/etc/postfix/\fIfilename\fB <\fIinputfile\fR +.SH DESCRIPTION +.ad +.fi +The Postfix mail system uses optional tables for address +rewriting or mail routing. These tables are usually in +\fBdbm\fR or \fBdb\fR format. + +Alternatively, lookup tables can be specified as MongoDB +databases. In order to use MongoDB lookups, define a MongoDB +source as a lookup table in main.cf, for example: +.nf + alias_maps = mongodb:/etc/postfix/mongodb\-aliases.cf +.fi + +In this example, the file /etc/postfix/mongodb\-aliases.cf +has the same format as the Postfix main.cf file, and can +specify the parameters described below. It is also possible +to have the configuration in main.cf; see "OBSOLETE MAIN.CF +PARAMETERS" below. + +It is strongly recommended to use proxy:mongodb, in order +to reduce the number of database connections. For example: +.nf + alias_maps = proxy:mongodb:/etc/postfix/mongodb\-aliases.cf +.fi + +Note: when using proxy:mongodb:/\fIfile\fR, the file must +be readable by the unprivileged postfix user (specified +with the Postfix mail_owner configuration parameter). +.SH "MONGODB PARAMETERS" +.na +.nf +.ad +.fi +.IP "\fBuri\fR" +The URI of mongo server/cluster that Postfix will try to +connect to and query from. Please see +.nf +https://www.mongodb.com/docs/manual/reference/connection\-string/ +.fi + +Example: +.nf + uri = mongodb+srv://user:pass@loclhost:27017/mail +.fi +.IP "\fBdbname\fR" +Name of the database to read the information from. +Example: +.nf + dbname = mail +.fi +.IP "\fBcollection\fR" +Name of the collection (table) to read the information from. +Example: +.nf + collection = mailbox +.fi +.IP "\fBquery_filter\fR" +The MongoDB query template used to search the database, +where \fB%s\fR is a substitute for the email address that +Postfix is trying to resolve. Please see: +.nf +https://www.mongodb.com/docs/manual/tutorial/query\-documents/ +.fi + +Example: +.nf + query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1} +.fi + +This parameter supports the following '%' expansions: +.RS +.IP "\fB%%\fR" +This is replaced by a literal '%' character. +.IP "\fB%s\fR" +This is replaced by the input key. The %s must appear in +quotes, because all Postfix queries are strings containing +(parts from) a domain or email address. Postfix makes no +numerical queries. +.IP "\fB%u\fR" +When the input key is an address of the form user@domain, +\fB%u\fR is replaced by the local part of the address. +Otherwise, \fB%u\fR is replaced by the entire search string. +.IP "\fB%d\fR" +When the input key is an address of the form user@domain, +\fB%d\fR is replaced by the domain part of the address. +.IP "\fB%[1\-9]\fR" +The patterns %1, %2, ... %9 are replaced by the corresponding +most significant component of the input key's domain. If +the input key is \fIuser@mail.example.com\fR, then %1 is +\fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR. +.RE +.IP +In the above substitutions, characters will be quoted as +required by RFC 4627. For example, each double quote or +backslash character will be escaped with a backslash +characacter. +.IP "\fBprojection\fR" +Advanced MongoDB query projections. Please see: +.nf +https://www.mongodb.com/docs/manual/tutorial/project\-fields\-from\-query\-results/ +.fi + +.RS +.IP \(bu +If \fBprojection\fR is non\-empty, then \fBresult_attribute\fR +must be empty. +.IP \(bu +This implementation can extract information only from result +fields that have type \fBstring\fR (UTF8), \fBinteger\fR +(int32, int64) and \fBarray\fR. Other result fields will +be ignored with a warning. Please see: +.nf +https://mongoc.org/libbson/current/bson_type_t.html +.fi +.IP \(bu +As with \fBresult_attribute\fR, the top\-level _id field +(type OID) is automatically removed from projection results. +.RE +.IP "\fBresult_attribute\fR" +Comma or whitespace separated list with the names of fields +to be returned in a lookup result. + +.RS +.IP \(bu +If \fBresult_attribute\fR is non\-empty, then \fBprojection\fR +must be empty. +.IP \(bu +As with \fBprojection\fR, the top\-level _id field (type +OID) is automatically removed from lookup results. +.RE +.IP "\fBresult_format (default: \fB%s\fR)\fR" +Format template applied to the result from \fBprojection\fR +or \fBresult_attribute\fR. Most commonly used to append (or +prepend) text to the result. This parameter supports the +following '%' expansions: +.RS +.IP "\fB%%\fR" +This is replaced by a literal '%' character. +.IP "\fB%s\fR" +This is replaced by the value of the result attribute. When +result is empty it is skipped. +.IP "\fB%u\fR +When the result attribute value is an address of the form +user@domain, \fB%u\fR is replaced by the local part of the +address. When the result has an empty localpart it is +skipped. +.IP "\fB%d\fR" +When a result attribute value is an address of the form +user@domain, \fB%d\fR is replaced by the domain part of the +attribute value. When the result is unqualified it is +skipped. +.IP "\fB%[SUD1\-9]\fR" +The upper\-case and decimal digit expansions interpolate the +parts of the input key rather than the result. Their behavior +is identical to that described with \fBquery_filter\fR, and +in fact because the input key is known in advance, lookups +whose key does not contain all the information specified +in the result template are suppressed and return no results. +.RE +.IP +For example, using "result_format = smtp:[%s]" allows one +to use a mailHost attribute as the basis of a transport(5) +table. After applying the result format, multiple values +are concatenated as comma separated strings. The expansion_limit +parameter explained below allows one to restrict the number +of values in the result, which is especially useful for +maps that should return a single value. + +The default value \fB%s\fR specifies that each +attribute value should be used as is. + +NOTE: DO NOT put quotes around the result format! The result +is not a JSON string. +.IP "\fBdomain (default: no domain list)\fR" +This is a list of domain names, paths to files, or "type:table" +databases. When specified, only fully qualified search keys +with a *non\-empty* localpart and a matching domain are +eligible for lookup: 'user' lookups, bare domain lookups +and "@domain" lookups are not performed. This can significantly +reduce the query load on the backend database. Example: +.nf + domain = postfix.org, hash:/etc/postfix/searchdomains +.fi +.IP "\fBexpansion_limit (default: 0)\fR" +A limit on the total number of result elements returned (as +a comma separated list) by a lookup against the map. A +setting of zero disables the limit. Lookups fail with a +temporary error if the limit is exceeded. Setting the limit +to 1 ensures that lookups do not return multiple values. +.SH "OBSOLETE MAIN.CF PARAMETERS" +.na +.nf +.ad +.fi +MongoDB parameters can also be defined in main.cf. Specify +as MongoDB source a name that doesn't begin with a slash +or a dot. The MongoDB parameters will then be accessible +as the name you've given the source in its definition, an +underscore, and the name of the parameter. For example, if +a map is specified as "mongodb:\fImongodb_source\fR", the +"uri" parameter would be defined in main.cf as +"\fImongodb_source\fR_uri". + +Note: with this form, passwords are written in main.cf, +which is normally world\-readable, and '$' in a mongodb +parameter setting needs to be written as '$$'. +.SH "SEE ALSO" +.na +.nf +postmap(1), Postfix lookup table maintenance +postconf(5), configuration parameters +.SH "README FILES" +.na +.nf +.ad +.fi +Use "\fBpostconf readme_directory\fR" or "\fBpostconf +html_directory\fR" to locate this information. +.na +.nf +DATABASE_README, Postfix lookup table overview +MONGODB_README, Postfix MONGODB client guide +.SH "LICENSE" +.na +.nf +.ad +.fi +The Secure Mailer license must be distributed with this software. +.SH HISTORY +.ad +.fi +MongoDB support was introduced with Postfix version 3.9. +.SH "AUTHOR(S)" +.na +.nf +Hamid Maadani (hamid@dexo.tech) +Dextrous Technologies, LLC + +Edited by: +Wietse Venema +porcupine.org + +Based on prior work by: +Stephan Ferraro +Aionda GmbH diff --git a/man/man5/mysql_table.5 b/man/man5/mysql_table.5 index 2b01aca..aebb949 100644 --- a/man/man5/mysql_table.5 +++ b/man/man5/mysql_table.5 @@ -89,6 +89,24 @@ The database name on the servers. Example: .nf dbname = customer_database .fi +.IP "\fBcharset (default: utf8mb4)\fR" +The default MySQL client character set; this also implies +the collation order. + +This parameter is available with Postfix 3.9 and later. +With earlier Postfix versions, the default was chosen by +the MySQL implementation (\fButf8mb4\fR as of MySQL 8.0, +\fBlatin1\fR historically). +.IP "\fBidle_interval (default: 60)\fR" +The number of seconds after which an idle database connection +will be closed. + +This feature is available in Postfix 3.9 and later. +.IP "\fBretry_interval (default: 60)\fR" +The number of seconds that a database connection will be +skipped after an error. + +This feature is available in Postfix 3.9 and later. .IP "\fBquery\fR" The SQL query template used to search the database, where \fB%s\fR is a substitute for the address Postfix is trying to resolve, diff --git a/man/man5/pcre_table.5 b/man/man5/pcre_table.5 index a9fd7b6..b5adb94 100644 --- a/man/man5/pcre_table.5 +++ b/man/man5/pcre_table.5 @@ -206,9 +206,14 @@ in\-memory file: Postfix parses the result as if it is a file in /etc/postfix. -Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep -Postfix from trying to do \fI$name\fR expansion as it -evaluates a parameter value. +Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +to keep Postfix from trying to do \fI$name\fR expansion as +it evaluates a parameter value. + +Note: when using \fI$name\fR inside an inlined pattern, use +\eQ\fI$name\fR\eE to disable metacharacters such as '.' in +the \fI$name\fR expansion. Otherwise, the pattern may have +unexpected matches. .SH "EXAMPLE SMTPD ACCESS MAP" .na .nf diff --git a/man/man5/pgsql_table.5 b/man/man5/pgsql_table.5 index 00a2da3..869a635 100644 --- a/man/man5/pgsql_table.5 +++ b/man/man5/pgsql_table.5 @@ -90,10 +90,21 @@ is: .nf encoding = UTF8 .fi + Historically, the database client was hard coded to use LATIN1 in an attempt to disable multibyte character support. This feature is available in Postfix 3.8 and later. +.IP "\fBidle_interval (default: 60)\fR" +The number of seconds after which an idle database connection +will be closed. + +This feature is available in Postfix 3.9 and later. +.IP "\fBretry_interval (default: 60)\fR" +The number of seconds that a database connection will be +skipped after an error. + +This feature is available in Postfix 3.9 and later. .IP "\fBquery\fR" The SQL query template used to search the database, where \fB%s\fR is a substitute for the address Postfix is trying to resolve, diff --git a/man/man5/postconf.5 b/man/man5/postconf.5 index 196a700..cf96e48 100644 --- a/man/man5/postconf.5 +++ b/man/man5/postconf.5 @@ -358,8 +358,13 @@ alias_database = hash:/etc/mail/aliases .ad .ft R .SH alias_maps (default: see "postconf \-d" output) -The alias databases that are used for \fBlocal\fR(8) delivery. See -\fBaliases\fR(5) for syntax details. +Optional lookup tables with aliases that apply only to \fBlocal\fR(8) +recipients; this is unlike virtual_alias_maps that apply to all +recipients: \fBlocal\fR(8), virtual, and remote. +The table format and lookups are documented in \fBaliases\fR(5). For an +overview of Postfix address manipulations see the ADDRESS_REWRITING_README +document. +.PP Specify zero or more "type:name" lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. @@ -1773,16 +1778,25 @@ name of the message delivery transport. This feature is available in Postfix 2.4 and later. .SH default_transport (default: smtp) The default mail delivery transport and next\-hop destination for -destinations that do not match $mydestination, $inet_interfaces, +the default domain class: recipient domains that do not match +$mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, -or $relay_domains. This information can be overruled with the -sender_dependent_default_transport_maps parameter and with the -\fBtransport\fR(5) table. +or $relay_domains. This information will not be used when +sender_dependent_default_transport_maps returns a result, and may +be overridden with the \fBtransport\fR(5) table. .PP -In order of decreasing precedence, the nexthop destination is taken -from $sender_dependent_default_transport_maps, $default_transport, -$sender_dependent_relayhost_maps, $relayhost, or from the recipient +For recipient domains in the default domain class: +.IP \(bu +In order of decreasing precedence, the delivery transport +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport. +.IP \(bu +In order of decreasing precedence, the nexthop destination +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient domain. +.br .PP Specify a string of the form \fItransport:nexthop\fR, where \fItransport\fR is the name of a mail delivery transport defined in master.cf. @@ -2367,6 +2381,19 @@ logfiles with the queue file names of mail that is queued for those destinations. .PP This feature is available in Postfix 2.0 and later. +.SH force_mime_input_conversion (default: no) +Convert body content that claims to be 8\-bit into quoted\-printable, +before header_checks, body_checks, Milters, and before after\-queue +content filters. This feature does not affect messages that are +sent into smtpd_proxy_filter. +.PP +The typical use case is an MTA that applies this conversion +before signing outbound messages, so that the signatures will remain +valid when a message is later delivered to an MTA that does not +announce 8BITMIME support, or when a message line exceeds the SMTP +length limit. +.PP +This feature is available in Postfix >= 3.9. .SH fork_attempts (default: 5) The maximal number of attempts to fork() a child process. .SH fork_delay (default: 1s) @@ -2416,7 +2443,7 @@ The entire recipient localpart. The address extension delimiter that was found in the recipient address (Postfix 2.11 and later), or the 'first' delimiter specified with the system\-wide recipient address extension delimiter (Postfix -3.5.22, 3.5.12, 3.7.8, 3.8.3 and later). Historically, this was +3.5.22, 3.6.12, 3.7.8, 3.8.3 and later). Historically, this was always the system\-wide recipient address extension delimiter (Postfix 2.10 and earlier). .br @@ -2628,31 +2655,55 @@ number of messages delivered per second. .PP Specify 0 to disable the feature. Valid delays are 0..10. .SH inet_interfaces (default: all) -The local network interface addresses that this mail system receives -mail on. Specify "all" to receive mail on all network -interfaces (default), and "loopback\-only" to receive mail -on loopback network interfaces only (Postfix version 2.2 and later). The -parameter also controls delivery of mail to user@[ip.address]. +The local network interface addresses that this mail system +receives mail on. Specify "all" to receive mail on all network +interfaces (default), "loopback\-only" to receive mail on loopback +network interfaces only (Postfix version 2.2 and later), or zero +or more IPv4 or IPv6 addresses (IPv6 is supported in Postfix version +2.2 and later). The parameter also controls whether Postfix will +accept mail for user@[ip.address], and prevents Postfix +from delivering mail to a host that has equal or larger MX preference. +Specify an empty value if Postfix does not receive mail over the +network, or if all network listeners have an explicit IP address +in master.cf. .PP Note 1: you need to stop and start Postfix when this parameter changes. .PP Note 2: address information may be enclosed inside [], but this form is not required here. .PP -When inet_interfaces specifies just one IPv4 and/or IPv6 address -that is not a loopback address, the Postfix SMTP client will use -this address as the IP source address for outbound mail. Support -for IPv6 is available in Postfix version 2.2 and later. +When smtp_bind_address and/or smtp_bind_address6 are not +specified, the inet_interfaces setting may constrain the source IP +address for an outbound SMTP or LMTP connection as described below. +.PP +The following text is specific to SMTP and IPv4. The same +reasoning applies to the IPv6 protocol, and to the Postfix LMTP +client. To disable IPv4 or IPv6 support in the Postfix SMTP and +LMTP client, use inet_protocols. +.IP \(bu +When inet_interfaces specifies one IPv4 address, and that +is not a loopback address, the Postfix SMTP client uses that as the +source address for outbound IPv4 connections. +.IP \(bu +Otherwise, the Postfix SMTP client does not constrain the +source IPv4 address, and connects using a system\-chosen source IPv4 +address. This includes the cases where inet_interfaces is empty, +where it specifies \fBall\fR, or where it contains no IPv4 address, +one IPv4 address that is a loopback address, or multiple IPv4 +addresses. +.br .PP -On a multi\-homed firewall with separate Postfix instances listening on the -"inside" and "outside" interfaces, this can prevent each instance from -being able to reach remote SMTP servers on the "other side" of the -firewall. Setting -smtp_bind_address to 0.0.0.0 avoids the potential problem for -IPv4, and setting smtp_bind_address6 to :: solves the problem -for IPv6. +A Postfix SMTP client may fail to reach some remote SMTP servers +when the client source IP address is constrained explicitly with +smtp_bind_address or smtp_bind_address6, or implicitly with +inet_interfaces. This can happen when Postfix runs on a multi\-homed +system such as a firewall, the Postfix SMTP source client IP address +is constrained to one specific network interface, and the remote +SMTP server must be reached through a different interface. Setting +smtp_bind_address to 0.0.0.0 avoids the potential problem for IPv4, +and setting smtp_bind_address6 to :: solves the problem for IPv6. .PP -A better solution for multi\-homed firewalls is to leave inet_interfaces +A better solution for multi\-homed systems is to leave inet_interfaces at the default value and instead use explicit IP addresses in the master.cf SMTP server definitions. This preserves the Postfix SMTP client's @@ -2679,7 +2730,7 @@ inet_interfaces = 192.168.1.2, 127.0.0.1 .fi .ad .ft R -.SH inet_protocols (default: see 'postconf \-d output') +.SH inet_protocols (default: see 'postconf \-d' output) The Internet protocols Postfix will attempt to use when making or accepting connections. Specify one or more of "ipv4" or "ipv6", separated by whitespace or commas. The form @@ -3093,6 +3144,9 @@ This feature is available in Postfix 2.11 and later. The LMTP\-specific version of the smtp_enforce_tls configuration parameter. See there for details. .PP +This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_security_level instead. +.PP This feature is available in Postfix 2.3 and later. .SH lmtp_fallback_relay (default: empty) Optional list of relay hosts for LMTP destinations that can't be @@ -3289,6 +3343,9 @@ Optional Postfix LMTP client lookup tables with one username:password entry per host or domain. If a remote host or domain has no username:password entry, then the Postfix LMTP client will not attempt to authenticate to the remote host. +.SH lmtp_sasl_password_result_delimiter (default: :) +The LMTP\-specific version of the smtp_sasl_password_result_delimiter +configuration parameter. See there for details. .SH lmtp_sasl_path (default: empty) Implementation\-specific information that is passed through to the SASL plug\-in implementation that is selected with @@ -3437,6 +3494,11 @@ parameter. See there for details. .PP This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. +.SH lmtp_tls_enable_rpk (default: yes) +The LMTP\-specific version of the smtp_tls_enable_rpk +configuration parameter. See there for details. +.PP +This feature is available in Postfix 3.9 and later. .SH lmtp_tls_enforce_peername (default: yes) The LMTP\-specific version of the smtp_tls_enforce_peername configuration parameter. See there for details. @@ -3482,7 +3544,7 @@ The LMTP\-specific version of the smtp_tls_mandatory_exclude_ciphers configuration parameter. See there for details. .PP This feature is available in Postfix 2.3 and later. -.SH lmtp_tls_mandatory_protocols (default: see postconf \-d output) +.SH lmtp_tls_mandatory_protocols (default: see 'postconf \-d' output) The LMTP\-specific version of the smtp_tls_mandatory_protocols configuration parameter. See there for details. .PP @@ -3496,13 +3558,16 @@ This feature is available in Postfix 2.3 and later. The LMTP\-specific version of the smtp_tls_per_site configuration parameter. See there for details. .PP +This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_policy_maps instead. +.PP This feature is available in Postfix 2.3 and later. .SH lmtp_tls_policy_maps (default: empty) The LMTP\-specific version of the smtp_tls_policy_maps configuration parameter. See there for details. .PP This feature is available in Postfix 2.3 and later. -.SH lmtp_tls_protocols (default: see postconf \-d output) +.SH lmtp_tls_protocols (default: see 'postconf \-d' output) The LMTP\-specific version of the smtp_tls_protocols configuration parameter. See there for details. .PP @@ -3556,6 +3621,9 @@ This feature is available in Postfix 3.0 and later. The LMTP\-specific version of the smtp_use_tls configuration parameter. See there for details. .PP +This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_security_level instead. +.PP This feature is available in Postfix 2.3 and later. .SH lmtp_xforward_timeout (default: 300s) The Postfix LMTP client time limit for sending the XFORWARD command, @@ -3803,7 +3871,8 @@ whitespace or comma. Tables will be searched in the specified order until a match is found. .PP If this parameter is non\-empty (the default), then the Postfix SMTP -server will reject mail for unknown local users. +server will reject mail for unknown local users. Other Postfix +interfaces may still accept an "unknown" recipient. .PP To turn off local recipient checking in the Postfix SMTP server, specify "local_recipient_maps =" (i.e. empty). @@ -3989,6 +4058,10 @@ Remote client protocol. Available in Postfix version 2.2 and later. .IP "\fBDOMAIN\fR" The domain part of the recipient address. .br +.IP "\fBENVID\fR" +The optional RFC 3461 envelope ID. Available in Postfix version +3.9 and later +.br .IP "\fBEXTENSION\fR" The optional address extension. .br @@ -4141,6 +4214,15 @@ logrotate". The command is run with the rotated logfile name as its first argument. .PP This feature is available in Postfix 3.4 and later. +.SH maillog_file_permissions (default: 0600) +The file access permissions that will be set when the file +$maillog_file is created for the first time, or when the file is +created after an existing file is rotated. Specify one of: \fB0600\fR +(only super\-user read/write access), \fB0640\fR (adds 'group' read +access), or \fB0644\fR (also adds 'other' read access). The leading +\&'0' is optional. +.PP +This feature is available in Postfix 3.9 and later. .SH maillog_file_prefixes (default: /var, /dev/stdout) A list of allowed prefixes for a maillog_file value. This is a safety feature to contain the damage from a single configuration @@ -5249,9 +5331,9 @@ it passes the test, before it can talk to a real Postfix SMTP server. .PP This feature is available in Postfix 2.8. .SH postscreen_bare_newline_ttl (default: 30d) -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful "bare newline" SMTP protocol test. During this -time, the client IP address is excluded from this test. The default +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a "bare newline" SMTP protocol test, before it +address is required to pass that test again. The default is long because a remote SMTP client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server. @@ -5411,18 +5493,19 @@ defined with the postscreen_dnsbl_sites parameter. Specify a negative value to enable this feature. When a client passes the postscreen_dnsbl_allowlist_threshold without having failed other tests, all pending or disabled tests are flagged as -completed with a time\-to\-live value equal to postscreen_dnsbl_ttl. -When a test was already completed, its time\-to\-live value is updated -if it was less than postscreen_dnsbl_ttl. +completed with an expiration time based on the DNS reply TTL. +When a test was already completed, its expiration time is updated +if it was less than the value based on the DNS reply TTL. See +also postscreen_dnsbl_max_ttl and postscreen_dnsbl_min_ttl. .PP This feature is available in Postfix 3.6 and later. .PP Available as postscreen_dnsbl_whitelist_threshold in Postfix 2.11 \- 3.5. .SH postscreen_dnsbl_max_ttl (default: ${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h) -The maximum amount of time that \fBpostscreen\fR(8) will use the -result from a successful DNS\-based reputation test before a -client IP address is required to pass that test again. If the DNS +The maximum amount of time that \fBpostscreen\fR(8) remembers that a +client IP address passed a DNS\-based reputation test, before it is +required to pass that test again. If the DNS reply specifies a shorter TTL value, that value will be used unless it would be smaller than postscreen_dnsbl_min_ttl. .PP @@ -5434,9 +5517,9 @@ The default time unit is h (hours). This feature is available in Postfix 3.1. The default setting is backwards\-compatible with older Postfix versions. .SH postscreen_dnsbl_min_ttl (default: 60s) -The minimum amount of time that \fBpostscreen\fR(8) will use the -result from a successful DNS\-based reputation test before a -client IP address is required to pass that test again. If the DNS +The minimum amount of time that \fBpostscreen\fR(8) remembers that a +client IP address passed a DNS\-based reputation test, before it +is required to pass that test again. If the DNS reply specifies a larger TTL value, that value will be used unless it would be larger than postscreen_dnsbl_max_ttl. .PP @@ -5559,9 +5642,9 @@ The default time unit is s (seconds). .PP This feature is available in Postfix 3.0. .SH postscreen_dnsbl_ttl (default: 1h) -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful DNS\-based reputation test before a client -IP address is required to pass that test again. +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a DNS\-based reputation test, before it is required +to pass that test again. .PP Specify a non\-zero time value (an integral value plus an optional one\-letter suffix that specifies the time unit). Time units: s @@ -5628,9 +5711,9 @@ value to disable this feature. .PP This feature is available in Postfix 2.8. .SH postscreen_greet_ttl (default: 1d) -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful PREGREET test. During this time, the client IP address -is excluded from this test. The default is relatively short, because +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a PREGREET test, before it is required to pass +that test again. The default is relatively short, because a good client can immediately talk to a real Postfix SMTP server. .PP Specify a non\-zero time value (an integral value plus an optional @@ -5688,9 +5771,9 @@ test, before it can talk to a real Postfix SMTP server. .PP This feature is available in Postfix 2.8. .SH postscreen_non_smtp_command_ttl (default: 30d) -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful "non_smtp_command" SMTP protocol test. During this -time, the client IP address is excluded from this test. The default +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a "non_smtp_command" SMTP protocol test, before +it is required to pass that test again. The default is long because a client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server. .PP @@ -5732,9 +5815,9 @@ server. .PP This feature is available in Postfix 2.8. .SH postscreen_pipelining_ttl (default: 30d) -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful "pipelining" SMTP protocol test. During this time, the -client IP address is excluded from this test. The default is +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a "pipelining" SMTP protocol test, before it is +required to pass that test again. The default is long because a good client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server. .PP @@ -6408,11 +6491,19 @@ relay_recipient_maps = hash:/etc/postfix/relay_recipients This feature is available in Postfix 2.0 and later. .SH relay_transport (default: relay) The default mail delivery transport and next\-hop destination for -remote delivery to domains listed with $relay_domains. In order of -decreasing precedence, the nexthop destination is taken from -$relay_transport, $sender_dependent_relayhost_maps, $relayhost, or -from the recipient domain. This information can be overruled with -the \fBtransport\fR(5) table. +the relay domain address class: recipient domains that match +$relay_domains. +.PP +For recipient domains in the relay domain address class: +.IP \(bu +In order of decreasing precedence, the message delivery +transport is taken from 1) $transport_maps, 2) $relay_transport. +.IP \(bu +In order of decreasing precedence, the nexthop destination +is taken from 1) $transport_maps, 2) $relay_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain. +.br .PP Specify a string of the form \fItransport:nexthop\fR, where \fItransport\fR is the name of a mail delivery transport defined in master.cf. @@ -6424,21 +6515,37 @@ file. .PP This feature is available in Postfix 2.0 and later. .SH relayhost (default: empty) -The next\-hop destination(s) for non\-local mail; overrides non\-local -domains in recipient addresses. This information is overruled with -relay_transport, sender_dependent_default_transport_maps, -default_transport, sender_dependent_relayhost_maps -and with the \fBtransport\fR(5) table. +The next\-hop destination(s) for non\-local mail; takes precedence +over non\-local domains in recipient addresses. This information +will not be used when the sender matches $sender_dependent_relayhost_maps. +.PP +In order of decreasing precedence: +.IP \(bu +For recipient domains in the relay domain address class +(domains matching $relay_domains), the nexthop destination is taken +from 1) $transport_maps, 2) $relay_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain. +.IP \(bu +For recipient domains in the default domain address class +(domains that do not match $mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +or $relay_domains), the nexthop destination is taken from 1) +$transport_maps, 2) $sender_dependent_default_transport_maps or +$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost +or the recipient domain. +.br .PP On an intranet, specify the organizational domain name. If your internal DNS uses no MX records, specify the name of the intranet gateway host instead. .PP -In the case of SMTP or LMTP delivery, specify one or more destinations -in the form of a domain name, hostname, hostname:port, [hostname]:port, -[hostaddress] or [hostaddress]:port, separated by comma or whitespace. -The form [hostname] turns off MX lookups. Multiple destinations are -supported in Postfix 3.5 and later. +In the case of SMTP delivery, specify one or more destinations in +the form of a domain name, hostname, hostname:service, [hostname]:service, +[hostaddress] or [hostaddress]:service, separated by comma or whitespace. +The form [hostname] turns off MX or SRV lookups. Multiple destinations +are supported in Postfix 3.5 and later. Each destination is tried +in the specified order. .PP If you're connected via UUCP, see the UUCP_README file for useful information. @@ -6719,9 +6826,21 @@ address and @domain. A lookup result of DUNNO terminates the search without overriding the global default_transport parameter setting. This information is overruled with the \fBtransport\fR(5) table. .PP -Specify zero or more "type:name" lookup tables, separated by -whitespace or comma. Tables will be searched in the specified order -until a match is found. +This setting affects only the default domain address class +(recipient domains that do not match $mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +or $relay_domains): +.IP \(bu +In order of decreasing precedence, the delivery transport +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport. +.IP \(bu +In order of decreasing precedence, the nexthop destination +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain. +.br .PP Note: this overrides default_transport, not transport_maps, and therefore the expected syntax is that of default_transport, not the @@ -6729,6 +6848,10 @@ syntax of transport_maps. Specifically, this does not support the transport_maps syntax for null transport, null nexthop, or null email addresses. .PP +Specify zero or more "type:name" lookup tables, separated by +whitespace or comma. Tables will be searched in the specified order +until a match is found. +.PP For safety reasons, this feature does not allow $number substitutions in regular expression maps. .PP @@ -6738,9 +6861,24 @@ A sender\-dependent override for the global relayhost parameter setting. The tables are searched by the envelope sender address and @domain. A lookup result of DUNNO terminates the search without overriding the global relayhost parameter setting (Postfix 2.6 and -later). This information is overruled with relay_transport, -sender_dependent_default_transport_maps, default_transport and with -the \fBtransport\fR(5) table. +later). +.PP +In order of decreasing precedence: +.IP \(bu +For recipient domains in the relay domain address class +(domains matching $relay_domains), the nexthop destination is taken +from 1) $transport_maps, 2) $relay_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain. +.IP \(bu +For recipient domains in the default domain address class +(domains that do not match mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +$relay_domains), the nexthop destination is taken from 1) +$transport_maps, 2) $sender_dependent_default_transport_maps or +$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost +or the recipient domain. +.br .PP Specify zero or more "type:name" lookup tables, separated by whitespace or comma. Tables will be searched in the specified order @@ -6871,12 +7009,45 @@ Notes for mail delivery between sites that have both IPv4 and IPv6 connectivity: .IP \(bu The setting "smtp_address_preference = ipv6" is unsafe. -It can fail to deliver mail when there is an outage that affects -IPv6, while the destination is still reachable over IPv4. +All deliveries will suffer delays during an IPv6 outage, even +while the destination is still reachable over IPv4. Mail may be +stuck in the queue with Postfix versions < 3.3 that do not +implement "smtp_balance_inet_protocols". For similar reasons, the +setting "smtp_address_preference = ipv4" is also unsafe. .IP \(bu The setting "smtp_address_preference = any" is safe. With -this, mail will eventually be delivered even if there is an outage +this, and "smtp_balance_inet_protocols = yes" (the default), only +half of deliveries will suffer delays if there is an outage that affects IPv6 or IPv4, as long as it does not affect both. +.IP \(bu +The setting "smtp_address_preference = ipv4" is not a +solution for remote servers that flag email received over IPv6 as +more 'spammy' (the client IPv6 address has a bad or missing PTR or +AAAA record, bad network neighbors, etc.). Instead, configure Postfix +to receive mail over both IPv4 and IPv6, and to deliver mail over +only IPv4. +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/main.cf: + inet_protocols = all +.fi +.ad +.ft R +.in -4 +.sp +.in +4 +.nf +.na +.ft C +/etc/postfix/master.cf + smtp ...other fields... smtp \-o inet_protocols=ipv4 +.fi +.ad +.ft R +.in -4 .br .PP This feature is available in Postfix 2.8 and later. @@ -7919,12 +8090,21 @@ lookup is done only when sender\-dependent authentication is enabled. If no username:password entry is found, then the Postfix SMTP client will not attempt to authenticate to the remote host. .PP +Use smtp_sasl_password_result_delimiter to specify an +alternative separator between username and password. +.PP The Postfix SMTP client opens the lookup table before going to chroot jail, so you can leave the password file in /etc/postfix. .PP Specify zero or more "type:name" lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. +.SH smtp_sasl_password_result_delimiter (default: :) +The delimiter between username and password in sasl_passwd_maps lookup +results. Specify one non\-whitespace character that does not appear in +the username. +.PP +This feature is available in Postfix >= 3.9. .SH smtp_sasl_path (default: empty) Implementation\-specific information that the Postfix SMTP client passes through to @@ -8507,6 +8687,89 @@ to anyone else. .PP This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. +.SH smtp_tls_enable_rpk (default: no) +Request that remote SMTP servers send an RFC7250 raw public key +instead of an X.509 certificate. This feature and the enable_rpk +policy attribute are ignored when there is no raw public key support +in the local TLS implementation. +.IP \(bu +At the "may", "encrypt" and "fingerprint" security levels, +with parameter setting "smtp_tls_enable_rpk = yes" or with "enable_rpk += yes" in a policy entry, the Postfix SMTP client will indicate in +the TLS handshake that it prefers to receive a raw server public +key, but it will still accept a server public key certificate. +.IP \(bu +At the "fingerprint" security level, with parameter setting +"smtp_tls_enable_rpk = yes" or with "enable_rpk = yes" in a policy +entry, server authentication based on certificate fingerprints +becomes more fragile. Even if the server private key and certificate +remain unchanged, the remote SMTP server will fail fingerprint +authentication (won't match the configured list of fingerprints) +when it starts sending a raw public key instead of a certificate, +after its TLS implementation is updated with raw public key support. +Therefore, \fBDO NOT\fR enable raw public keys to remote destinations +authenticated by server \fBcertificate\fR fingerprints. You should +enable raw public keys only for servers matched via their public +key fingerprint. +.IP \(bu +At the "verify" and "secure" security levels, the Postfix +SMTP client always ignores the parameter setting smtp_tls_enable_rpk +or the enable_rpk policy attribute. +.IP \(bu +At the opportunistic "dane" security level, the Postfix +SMTP client ignores the parameter setting smtp_tls_enable_rpk or +the enable_rpk policy attribute (but it will respect them when it +falls back to the "may" or "encrypt" level). When all valid TLSA +records specify only server public keys (no certificates) and the +local TLS implementation supports raw public keys, the client will +indicate in the TLS handshake that it prefers to receive a raw +public key, but it will still accept a public key certificate. +.IP \(bu +At the mandatory "dane\-only" security level, the Postfix +SMTP client always ignores the parameter setting smtp_tls_enable_rpk +or the enable_rpk policy attribute. When all valid TLSA records +specify only server public keys (no certificates) and the local TLS +implementation supports raw public keys, the client will indicate +in the TLS handshake that it prefers to receive a raw public key, +but it will still accept a public key certificate. +.br +.PP +The Postfix SMTP client is always willing to send raw public keys +to servers that solicit them when a client certificate is configured +and the local TLS implementation supports raw public keys. +.PP +Sample commands to compute certificate and public key SHA256 digests: +.PP +.nf +.na +.ft C +# SHA256 digest of the first certificate in "cert.pem" +$ openssl x509 \-in cert.pem \-outform DER | openssl dgst \-sha256 \-c +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +# SHA256 digest of the SPKI of the first certificate in "cert.pem" +$ openssl x509 \-in cert.pem \-pubkey \-noout | + openssl pkey \-pubin \-outform DER | openssl dgst \-sha256 \-c +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +# SHA256 digest of the SPKI of the first private key in "pkey.pem" +$ openssl pkey \-in pkey.pem \-pubout \-outform DER | + openssl dgst \-sha256 \-c +.fi +.ad +.ft R +.PP +This feature is available in Postfix 3.9 and later. .SH smtp_tls_enforce_peername (default: yes) With mandatory TLS encryption, require that the remote SMTP server hostname matches the information in the remote SMTP server @@ -8762,7 +9025,9 @@ With Postfix 2.8 and earlier, log the summary message and unconditionally log trust\-chain verification errors. .br .IP "" -2 Also log levels during TLS negotiation. +2 Also enable verbose logging in the Postfix TLS +library, log session cache operations, and enable OpenSSL logging +of the progress of the SSL handshake. .br .IP "" 3 Also log the hexadecimal and ASCII dump of the @@ -8997,7 +9262,9 @@ and smtp_tls_enforce_peername settings. .br .IP "MAY" Try to use TLS if the server announces support, -otherwise use an unencrypted connection. This has less precedence +otherwise use an unencrypted connection; after a failed TLS handshake +or TLS session, fall back to plaintext if the message has spent +minimal_backoff_time in the mail queue. This level 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 @@ -9084,28 +9351,35 @@ No TLS. No additional attributes are supported at this level. Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces interoperability. The optional "ciphers", "exclude", and "protocols" -attributes (available for opportunistic TLS with Postfix >= 2.6) -and "connection_reuse" attribute (Postfix >= 3.4) override the +attributes (available for opportunistic TLS with Postfix >= 2.6) and +"connection_reuse" attribute (Postfix >= 3.4) override the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols", -and -"smtp_tls_connection_reuse" configuration parameters. In the policy table, -multiple ciphers, protocols or excluded ciphers must be separated by colons, -as attribute values may not contain whitespace or commas. When opportunistic -TLS handshakes fail, Postfix retries the connection with TLS disabled. -This allows mail delivery to sites with non\-interoperable TLS -implementations. +and "smtp_tls_connection_reuse" configuration parameters. In the policy +table, multiple ciphers, protocols or excluded ciphers must be separated +by colons, as attribute values may not contain whitespace or commas. At +this level and higher, the optional "servername" attribute (available +with Postfix >= 3.4) overrides the global "smtp_tls_servername" +parameter, enabling per\-destination configuration of the SNI extension +sent to the remote SMTP server. The optional "enable_rpk" attribute +(Postfix >= 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. +When opportunistic TLS handshakes fail, Postfix retries the connection +with TLS disabled. This allows mail delivery to sites with +non\-interoperable TLS implementations. .br .IP "\fBencrypt\fR" -Mandatory TLS encryption. At this level -and higher, the optional "protocols" attribute overrides the main.cf +Mandatory TLS encryption. Mail is delivered only if the remote SMTP +server offers STARTTLS and the TLS handshake succeeds. At this level and +higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute -overrides the main.cf smtp_tls_mandatory_ciphers parameter, the -optional "exclude" attribute (Postfix >= 2.6) overrides the main.cf +overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional +"exclude" attribute (Postfix >= 2.6) overrides the main.cf smtp_tls_mandatory_exclude_ciphers parameter, and the optional -"connection_reuse" attribute (Postfix >= 3.4) overrides the -main.cf smtp_tls_connection_reuse parameter. In the policy table, -multiple ciphers, protocols or excluded ciphers must be separated by colons, -as attribute values may not contain whitespace or commas. +"connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. In the policy table, multiple +ciphers, protocols or excluded ciphers must be separated by colons, as +attribute values may not contain whitespace or commas. The optional +"enable_rpk" attribute (Postfix >= 3.9) overrides the main.cf +smtp_tls_enable_rpk parameter. .br .IP "\fBdane\fR" Opportunistic DANE TLS. The TLS policy for the destination is @@ -9144,10 +9418,10 @@ Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted Certification Authorities. The certificate trust chain, expiration date, ... are not checked. Instead, -the optional "match" attribute, or else the main.cf +the optional policy table "match" attribute, or else the main.cf \fBsmtp_tls_fingerprint_cert_match\fR parameter, lists the certificate -fingerprints or the public key fingerprint (Postfix 2.9 and later) -of the valid server certificate. The digest +fingerprints or the public key fingerprints (Postfix 2.9 and later) +of acceptable server certificates. The digest algorithm used to calculate the fingerprint is selected by the \fBsmtp_tls_fingerprint_digest\fR parameter. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple @@ -9158,45 +9432,58 @@ digits. The optional "ciphers", "exclude", and "protocols" attributes "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" configuration parameters. The optional "connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf smtp_tls_connection_reuse -parameter. +parameter. The optional "enable_rpk" attribute (Postfix >= 3.9) +overrides the main.cf smtp_tls_enable_rpk parameter. .br .IP "\fBverify\fR" -Mandatory TLS verification. At this security -level, DNS MX lookups are trusted to be secure enough, and the name -verified in the server certificate is usually obtained indirectly via -unauthenticated DNS MX lookups. The optional "match" attribute overrides -the main.cf smtp_tls_verify_cert_match parameter. In the policy table, -multiple match patterns and strategies must be separated by colons. -In practice explicit control over matching is more common with the -"secure" policy, described below. The optional "ciphers", "exclude", -and "protocols" attributes (Postfix >= 2.6) override the -"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and -"smtp_tls_mandatory_protocols" configuration parameters. The optional -"connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf -smtp_tls_connection_reuse parameter. +Mandatory TLS verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups are presumed to be +secure enough, and the name verified in the server certificate is +potentially obtained via unauthenticated DNS MX lookups. The optional +"match" attribute overrides the main.cf smtp_tls_verify_cert_match +parameter. In the policy table, multiple match patterns and strategies +must be separated by colons. In practice explicit control over matching +is more common with the "secure" policy, described below. The optional +"ciphers", "exclude", and "protocols" attributes (Postfix >= 2.6) +override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix >= 2.11 the optional "tafile" +policy table attribute modifies trust chain verification in the same +manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile" +attribute may be specified multiple times to load multiple trust\-anchor +files. The optional "connection_reuse" attribute (Postfix >= 3.4) +overrides the main.cf smtp_tls_connection_reuse parameter. .br .IP "\fBsecure\fR" -Secure\-channel TLS. At this security level, DNS -MX lookups, though potentially used to determine the candidate next\-hop -gateway IP addresses, are \fBnot\fR trusted to be secure enough for TLS -peername verification. Instead, the default name verified in the server -certificate is obtained directly from the next\-hop, or is explicitly -specified via the optional "match" attribute which overrides the -main.cf smtp_tls_secure_cert_match parameter. In the policy table, -multiple match patterns and strategies must be separated by colons. -The match attribute is most useful when multiple domains are supported by -a common server: the policy entries for additional domains specify matching -rules for the primary domain certificate. While transport table overrides -that route the secondary domains to the primary nexthop also allow secure -verification, they risk delivery to the wrong destination when domains -change hands or are re\-assigned to new gateways. With the "match" -attribute approach, routing is not perturbed, and mail is deferred if -verification of a new MX host fails. The optional "ciphers", "exclude", -and "protocols" attributes (Postfix >= 2.6) override the -"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and -"smtp_tls_mandatory_protocols" configuration parameters. The optional -"connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf -smtp_tls_connection_reuse parameter. +Secure certificate verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups, though potentially +used to determine the candidate next\-hop gateway IP addresses, are +\fBnot\fR presumed to be secure enough for TLS peername verification. +Instead, the default name verified in the server certificate is obtained +directly from the next\-hop, or is explicitly specified via the optional +"match" attribute which overrides the main.cf smtp_tls_secure_cert_match +parameter. In the policy table, multiple match patterns and strategies +must be separated by colons. The match attribute is most useful when +multiple domains are supported by a common server: the policy entries +for additional domains specify matching rules for the primary domain +certificate. While transport table overrides that route the secondary +domains to the primary nexthop also allow secure verification, they risk +delivery to the wrong destination when domains change hands or are +re\-assigned to new gateways. With the "match" attribute approach, +routing is not perturbed, and mail is deferred if verification of a new +MX host fails. The optional "ciphers", "exclude", and "protocols" +attributes (Postfix >= 2.6) override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix >= 2.11 the "tafile" attribute +optionally modifies trust chain verification in the same manner as the +"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be +specified multiple times to load multiple trust\-anchor files. The +optional "connection_reuse" attribute (Postfix >= 3.4) overrides the +main.cf smtp_tls_connection_reuse parameter. .br .br .PP @@ -9243,7 +9530,7 @@ DNS forgery. Do not use the "hostname" strategy for secure\-channel configurations in environments where DNS security is not assured. .PP This feature is available in Postfix 2.3 and later. -.SH smtp_tls_protocols (default: see postconf \-d output) +.SH smtp_tls_protocols (default: see 'postconf \-d' output) TLS protocols that the Postfix SMTP client will use with opportunistic TLS encryption. In main.cf the values are separated by whitespace, commas or colons. In the policy table "protocols" attribute @@ -9406,7 +9693,9 @@ destinations via smtp_tls_policy_maps. .br .IP "\fBmay\fR" Opportunistic TLS. Use TLS if this is supported by the remote -SMTP server, otherwise use plaintext. Since +SMTP server, otherwise use plaintext; after a failed TLS handshake +or TLS session, fall back to plaintext if the message has spent +minimal_backoff_time in the mail queue. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces interoperability. The "smtp_tls_ciphers" and "smtp_tls_protocols" (Postfix >= 2.6) @@ -10127,9 +10416,8 @@ pubkey_fingerprint } } The commas are optional. .br .IP "\fBcheck_client_access \fItype:table\fR\fR" -Search the specified access database for the client hostname, -parent domains, client IP address, or networks obtained by stripping -least significant octets. See the \fBaccess\fR(5) manual page for details. +Search the specified access database for the client hostname +or IP address. See the \fBaccess\fR(5) manual page for details. .br .IP "\fBcheck_client_a_access \fItype:table\fR\fR" Search the specified \fBaccess\fR(5) database for the IP addresses for the @@ -10156,8 +10444,7 @@ available in Postfix 2.7 and later. .br .IP "\fBcheck_reverse_client_hostname_access \fItype:table\fR\fR" Search the specified access database for the unverified reverse -client hostname, parent domains, client IP address, or networks -obtained by stripping least significant octets. See the \fBaccess\fR(5) +client hostname or IP address. See the \fBaccess\fR(5) manual page for details. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from denylists. This feature is available in Postfix 2.6 @@ -10684,6 +10971,9 @@ Note 2: when invoked via "\fBsendmail \-bs\fR", Postfix will never offer STARTTLS due to insufficient privileges to access the server private key. This is intended behavior. .PP +This feature is deprecated as of Postfix 3.9. Specify +smtpd_tls_security_level instead. +.PP This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead. .SH smtpd_error_sleep_time (default: 1s) @@ -10720,8 +11010,8 @@ restriction that matches wins. The following restrictions are specific to the domain name information received with the ETRN command. .IP "\fBcheck_etrn_access \fItype:table\fR\fR" -Search the specified access database for the ETRN domain name -or its parent domains. See the \fBaccess\fR(5) manual page for details. +Search the specified access database for the ETRN domain name. +See the \fBaccess\fR(5) manual page for details. .br .br .PP @@ -10752,7 +11042,7 @@ The smtpd_expansion_filter value is not subject to Postfix configuration parameter $name expansion. .PP This feature is available in Postfix 2.0 and later. -.SH smtpd_forbid_bare_newline (default: Postfix < 3.9: no) +.SH smtpd_forbid_bare_newline (default: Postfix >= 3.9: normalize) Reject or restrict input lines from an SMTP client that end in instead of the standard . Such line endings are commonly allowed with UNIX\-based SMTP servers, but they @@ -10761,7 +11051,7 @@ vulnerable to SMTP smuggling. .PP Specify one of the following values (case does not matter): -.IP "\fBnormalize\fR" +.IP "\fBnormalize\fR (default for Postfix >= 3.9)" Require the standard End\-of\-DATA sequence .. Otherwise, allow command or message content lines ending in the @@ -10780,6 +11070,17 @@ with the standard End\-of\-DATA sequence Such clients can be excluded with smtpd_forbid_bare_newline_exclusions. .br +.IP "\fBnote\fR" +Same as "normalize", but also notes in +the log whether the Postfix SMTP server received any lines with +"bare ". The information is formatted as "disconnect +from name[address] ... notes=bare_lf". The notes value is +expected to become a list of comma\-separated names. +.br +.br +This +feature is available in Postfix 3.9 and later. +.br .IP "\fByes\fR" Compatibility alias for \fBnormalize\fR. .br @@ -10808,9 +11109,8 @@ of BDAT violations, BDAT can be selectively disabled with smtpd_discard_ehlo_keyword_address_maps, or globally disabled with smtpd_discard_ehlo_keywords). .br -.IP "\fBno\fR (default)" -Do not require the standard -End\-of\-DATA +.IP "\fBno\fR (default for Postfix < 3.9)" +Do not require the standard End\-of\-DATA sequence .. Always process a bare as if the client sent . This option is fully backwards compatible, but is not recommended for @@ -10904,9 +11204,8 @@ This feature is available in Postfix >= 3.9, 3.8.5, 3.7.10, Disconnect remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. The server replies with "554 5.5.0 Error: SMTP protocol synchronization" and logs the unexpected remote -SMTP client input. Specify "smtpd_forbid_unauth_pipelining = yes" -to enable. This feature is enabled by default with Postfix >= -3.9. +SMTP client input. This feature is enabled by default with Postfix +>= 3.9. Specify "smtpd_forbid_unauth_pipelining = no" to disable. .PP This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6, 3.6.10, and 3.5.20. @@ -10964,7 +11263,7 @@ The following restrictions are specific to the hostname information received with the HELO or EHLO command. .IP "\fBcheck_helo_access \fItype:table\fR\fR" Search the specified \fBaccess\fR(5) database for the HELO or EHLO -hostname or parent domains, and execute the corresponding action. +hostname, and execute the corresponding action. Note: specify "smtpd_helo_required = yes" to fully enforce this restriction (without "smtpd_helo_required = yes", a client can simply skip check_helo_access by not sending HELO or EHLO). @@ -11430,8 +11729,7 @@ The following restrictions are specific to the recipient address that is received with the RCPT TO command. .IP "\fBcheck_recipient_access \fItype:table\fR\fR" Search the specified \fBaccess\fR(5) database for the resolved RCPT -TO address, domain, parent domains, or localpart@, and execute the -corresponding action. +TO address, and execute the corresponding action. .br .IP "\fBcheck_recipient_a_access \fItype:table\fR\fR" Search the specified \fBaccess\fR(5) database for the IP addresses for @@ -11809,7 +12107,7 @@ Continue long lines by starting the next line with whitespace. The same restrictions are available as documented under smtpd_recipient_restrictions. .PP -This feature is available in Postix 2.10 and later. +This feature is available in Postfix 2.10 and later. .SH smtpd_restriction_classes (default: empty) User\-defined aliases for groups of access restrictions. The aliases can be specified in smtpd_recipient_restrictions etc., and on the @@ -12089,8 +12387,7 @@ The following restrictions are specific to the sender address received with the MAIL FROM command. .IP "\fBcheck_sender_access \fItype:table\fR\fR" Search the specified \fBaccess\fR(5) database for the MAIL FROM -address, domain, parent domains, or localpart@, and execute the -corresponding action. +address, and execute the corresponding action. .br .IP "\fBcheck_sender_a_access \fItype:table\fR\fR" Search the specified \fBaccess\fR(5) database for the IP addresses for @@ -12903,6 +13200,59 @@ Postfix uses ciphers with forward secrecy. This feature is available in Postfix 2.6 and later, when it is compiled and linked with OpenSSL 1.0.0 or later on platforms where EC algorithms have not been disabled by the vendor. +.SH smtpd_tls_enable_rpk (default: no) +Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking for or requiring client +authentication. This feature is ignored when there is no raw public +key support in the local TLS implementation. +.PP +The Postfix SMTP server will log a warning when "smtpd_tls_enable_rpk += yes", but the remote SMTP client sends a certificate, the +certificate's public key fingerprint does not match a check_ccert_access +table, while the certificate fingerprint does match a check_ccert_access +table. The remote SMTP client would lose access when it starts +sending a raw public key instead of a certificate, after its TLS +implementation is updated with raw public key support. +.PP +The Postfix SMTP server always sends a raw public key instead +of a certificate, if solicited by the remote SMTP client and the +local TLS implementation supports raw public keys. If the client +sends a server name indication with an SNI TLS extension, and +tls_server_sni_maps is configured, the server will extract a raw +public key from the indicated certificate. +.PP +Sample commands to compute certificate and public key SHA256 digests: +.PP +.nf +.na +.ft C +# SHA256 digest of the first certificate in "cert.pem" +$ openssl x509 \-in cert.pem \-outform DER | openssl dgst \-sha256 \-c +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +# SHA256 digest of the SPKI of the first certificate in "cert.pem" +$ openssl x509 \-in cert.pem \-pubkey \-noout | + openssl pkey \-pubin \-outform DER | openssl dgst \-sha256 \-c +.fi +.ad +.ft R +.PP +.nf +.na +.ft C +# SHA256 digest of the SPKI of the first private key in "pkey.pem" +$ openssl pkey \-in pkey.pem \-pubout \-outform DER | + openssl dgst \-sha256 \-c +.fi +.ad +.ft R +.PP +This feature is available in Postfix 3.9 and later. .SH smtpd_tls_exclude_ciphers (default: empty) List of ciphers or cipher types to exclude from the SMTP server cipher list at all TLS security levels. Excluding valid ciphers @@ -13064,7 +13414,9 @@ earlier, log the summary message, peer certificate summary information and unconditionally log trust\-chain verification errors. .br .IP "" -2 Also log levels during TLS negotiation. +2 Also enable verbose logging in the Postfix TLS +library, log session cache operations, and enable OpenSSL logging +of the progress of the SSL handshake. .br .IP "" 3 Also log hexadecimal and ASCII dump of TLS negotiation @@ -13233,7 +13585,7 @@ smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 .ft R .PP This feature is available in Postfix 2.3 and later. -.SH smtpd_tls_protocols (default: see postconf \-d output) +.SH smtpd_tls_protocols (default: see 'postconf \-d' output) TLS protocols accepted by the Postfix SMTP server with opportunistic TLS encryption. If the list is empty, the server supports all available TLS protocol versions. A non\-empty value is a list of protocol names to @@ -13466,6 +13818,9 @@ Note: when invoked via "\fBsendmail \-bs\fR", Postfix will never offer STARTTLS due to insufficient privileges to access the server private key. This is intended behavior. .PP +This feature is deprecated as of Postfix 3.9. Specify +smtpd_tls_security_level instead. +.PP This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead. .SH smtputf8_autodetect_classes (default: sendmail, verify) @@ -13822,8 +14177,7 @@ via the tls_config_file parameter. When empty, or when the selected name is not present in the configuration file, the default application name ("openssl_conf") is used as a fallback. .PP -This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6, -3.6.10, and 3.5.20. +This feature is available in Postfix >= 3.9. .SH tls_daemon_random_bytes (default: 32) The number of pseudo\-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8) process requests from the \fBtlsmgr\fR(8) server in order to seed its @@ -14540,6 +14894,9 @@ Enforcement mode: require that SMTP servers use TLS encryption. See smtp_enforce_tls for further details. Use tlsproxy_client_security_level instead. .PP +This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_security_level instead. +.PP This feature is available in Postfix 3.4 and later. .SH tlsproxy_client_fingerprint_digest (default: $smtp_tls_fingerprint_digest) The message digest algorithm used to construct remote TLS server @@ -14575,6 +14932,9 @@ Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS usage policy by next\-hop destination and by remote TLS server hostname. See smtp_tls_per_site for further details. .PP +This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_policy_maps instead. +.PP This feature is available in Postfix 3.4 and later. .SH tlsproxy_client_policy (default: $smtp_tls_policy_maps) Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS @@ -14606,12 +14966,18 @@ Opportunistic mode: use TLS when a remote server announces TLS support. See smtp_use_tls for further details. Use tlsproxy_client_security_level instead. .PP +This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_security_level instead. +.PP This feature is available in Postfix 3.4 and later. .SH tlsproxy_enforce_tls (default: $smtpd_enforce_tls) Mandatory TLS: announce STARTTLS support to remote SMTP clients, and require that clients use TLS encryption. See smtpd_enforce_tls for further details. Use tlsproxy_tls_security_level instead. .PP +This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_tls_security_level instead. +.PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_service_name (default: tlsproxy) The name of the \fBtlsproxy\fR(8) service entry in master.cf. This @@ -14678,6 +15044,8 @@ File with DH parameters that the Postfix \fBtlsproxy\fR(8) server should use with non\-export EDH ciphers. See smtpd_tls_dh1024_param_file for further details. .PP +This feature is deprecated as of Postfix 3.9. Do not specify. +.PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_tls_dh512_param_file (default: $smtpd_tls_dh512_param_file) File with DH parameters that the Postfix \fBtlsproxy\fR(8) server @@ -14720,7 +15088,15 @@ The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral elliptic\-curve Diffie\-Hellman (EECDH) key exchange. See smtpd_tls_eecdh_grade for further details. .PP +This feature is deprecated as of Postfix 3.9. Do not specify. +.PP This feature is available in Postfix 2.8 and later. +.SH tlsproxy_tls_enable_rpk (default: $smtpd_tls_enable_rpk) +Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking or requiring client +authentication. See $smtpd_tls_enable_rpk for details. +.PP +This feature is available in Postfix 3.9 and later. .SH tlsproxy_tls_exclude_ciphers (default: $smtpd_tls_exclude_ciphers) List of ciphers or cipher types to exclude from the \fBtlsproxy\fR(8) server cipher list at all TLS security levels. See @@ -14799,6 +15175,9 @@ Opportunistic TLS: announce STARTTLS support to remote SMTP clients, but do not require that clients use TLS encryption. See smtpd_use_tls for further details. Use tlsproxy_tls_security_level instead. .PP +This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_tls_security_level instead. +.PP This feature is available in Postfix 2.8 and later. .SH tlsproxy_watchdog_timeout (default: 10s) How much time a \fBtlsproxy\fR(8) process may take to process local @@ -14952,7 +15331,13 @@ This feature is available in Postfix 2.5 and later. .SH transport_maps (default: empty) Optional lookup tables with mappings from recipient address to (message delivery transport, next\-hop destination). See \fBtransport\fR(5) -for details. +for syntax details. +.PP +This information may override the message delivery transport +and/or next\-hop destination that are specified with $local_transport, +$virtual_transport, $relay_transport, $default_transport, +$sender_dependent_relayhost_maps, $relayhost, +$sender_dependent_default_transport_maps, or the recipient domain. .PP Specify zero or more "type:table" lookup tables, separated by whitespace or comma. Tables will be searched in the specified order @@ -15421,8 +15806,10 @@ from each original recipient. .PP This feature is available in Postfix 2.1 and later. .SH virtual_alias_maps (default: $virtual_maps) -Optional lookup tables that alias specific mail addresses or domains -to other local or remote addresses. The table format and lookups +Optional lookup tables with aliases that apply to all recipients: +\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +only to \fBlocal\fR(8) recipients. +The table format and lookups are documented in \fBvirtual\fR(5). For an overview of Postfix address manipulations see the ADDRESS_REWRITING_README document. .PP diff --git a/man/man5/regexp_table.5 b/man/man5/regexp_table.5 index 9eeefe4..e969821 100644 --- a/man/man5/regexp_table.5 +++ b/man/man5/regexp_table.5 @@ -163,9 +163,14 @@ in\-memory file: Postfix parses the result as if it is a file in /etc/postfix. -Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep -Postfix from trying to do \fI$name\fR expansion as it -evaluates a parameter value. +Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +to keep Postfix from trying to do \fI$name\fR expansion as +it evaluates a parameter value. + +Note: when using \fI$name\fR inside an inlined pattern, +this will not disable metacharacters such as '.' in the +\fI$name\fR expansion. To prevent unexpected matches, use +a pcre: table, and specify \eQ\fI$name\fR\eE. .SH "EXAMPLE SMTPD ACCESS MAP" .na .nf diff --git a/man/man5/relocated.5 b/man/man5/relocated.5 index fbc85a3..e1d7863 100644 --- a/man/man5/relocated.5 +++ b/man/man5/relocated.5 @@ -147,8 +147,8 @@ domains that no longer exist. .PP Other parameters of interest: .IP "\fBinet_interfaces (all)\fR" -The network interface addresses that this mail system receives -mail on. +The local network interface addresses that this mail system +receives mail on. .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" The list of domains that are delivered via the $local_transport mail delivery transport. @@ -156,7 +156,7 @@ mail delivery transport. The domain name that locally\-posted mail appears to come from, and that locally posted mail is delivered to. .IP "\fBproxy_interfaces (empty)\fR" -The network interface addresses that this mail system receives mail +The remote network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit. .SH "SEE ALSO" .na diff --git a/man/man5/socketmap_table.5 b/man/man5/socketmap_table.5 index c53db3d..e5671dd 100644 --- a/man/man5/socketmap_table.5 +++ b/man/man5/socketmap_table.5 @@ -19,7 +19,7 @@ Postfix socketmap table lookup client .ad .fi The Postfix mail system uses optional tables for address -rewriting. mail routing or policy lookup. +rewriting, mail routing or policy lookup. The Postfix socketmap client expects TCP endpoint names of the form \fBinet:\fIhost\fB:\fIport\fB:\fIname\fR, or diff --git a/man/man5/virtual.5 b/man/man5/virtual.5 index 5a66c7f..e03a500 100644 --- a/man/man5/virtual.5 +++ b/man/man5/virtual.5 @@ -16,13 +16,14 @@ Postfix virtual alias table format .SH DESCRIPTION .ad .fi -The optional \fBvirtual\fR(5) alias table rewrites recipient -addresses for all local, all virtual, and all remote mail -destinations. -This is unlike the \fBaliases\fR(5) table which is used -only for \fBlocal\fR(8) delivery. This feature is implemented +The optional \fBvirtual\fR(5) alias table (virtual_alias_maps) +applies to all recipients: local(8), virtual, and remote. +This feature is implemented in the Postfix \fBcleanup\fR(8) daemon before mail is queued. +This is unlike the \fBaliases\fR(5) table (alias_maps) which +applies only to \fBlocal\fR(8) recipients. + Virtual aliasing is recursive; to terminate recursion for a specific address, alias that address to itself. @@ -270,8 +271,9 @@ this topic. See the Postfix \fBmain.cf\fR file for syntax details and for default values. Use the "\fBpostfix reload\fR" command after a configuration change. .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" -Optional lookup tables that alias specific mail addresses or domains -to other local or remote addresses. +Optional lookup tables with aliases that apply to all recipients: +\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +only to \fBlocal\fR(8) recipients. .IP "\fBvirtual_alias_domains ($virtual_alias_maps)\fR" Postfix is the final destination for the specified list of virtual alias domains, that is, domains for which all addresses are aliased @@ -282,8 +284,8 @@ key to the lookup result. .PP Other parameters of interest: .IP "\fBinet_interfaces (all)\fR" -The network interface addresses that this mail system receives -mail on. +The local network interface addresses that this mail system +receives mail on. .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" The list of domains that are delivered via the $local_transport mail delivery transport. @@ -296,7 +298,7 @@ Enable special treatment for owner\-\fIlistname\fR entries in the \fIlistname\fR\-request address localparts when the recipient_delimiter is set to "\-". .IP "\fBproxy_interfaces (empty)\fR" -The network interface addresses that this mail system receives mail +The remote network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit. .SH "SEE ALSO" .na diff --git a/man/man8/cleanup.8 b/man/man8/cleanup.8 index bc51c31..0f4ee68 100644 --- a/man/man8/cleanup.8 +++ b/man/man8/cleanup.8 @@ -286,10 +286,10 @@ that is received by the Postfix mail system. Available in Postfix version 2.1 and later: .IP "\fBsender_bcc_maps (empty)\fR" Optional BCC (blind carbon\-copy) address lookup tables, indexed -by sender address. +by envelope sender address. .IP "\fBrecipient_bcc_maps (empty)\fR" Optional BCC (blind carbon\-copy) address lookup tables, indexed by -recipient address. +envelope recipient address. .SH "ADDRESS TRANSFORMATION CONTROLS" .na .nf @@ -329,8 +329,9 @@ remote domains. .PP Available in Postfix version 2.0 and later: .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" -Optional lookup tables that alias specific mail addresses or domains -to other local or remote address. +Optional lookup tables with aliases that apply to all recipients: +\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +only to \fBlocal\fR(8) recipients. .PP Available in Postfix version 2.2 and later: .IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR" @@ -342,9 +343,10 @@ mapping. What addresses are subject to sender_canonical_maps address mapping. .IP "\fBremote_header_rewrite_domain (empty)\fR" -Don't rewrite message headers from remote clients at all when -this parameter is empty; otherwise, rewrite message headers and -append the specified domain name to incomplete addresses. +Rewrite or add message headers in mail from remote clients if +the remote_header_rewrite_domain parameter value is non\-empty, +updating incomplete addresses with the domain specified in the +remote_header_rewrite_domain parameter, and adding missing headers. .SH "RESOURCE AND RATE CONTROLS" .na .nf @@ -395,7 +397,7 @@ The maximal length of an email address after virtual alias expansion. Preliminary SMTPUTF8 support is introduced with Postfix 3.0. .IP "\fBsmtputf8_enable (yes)\fR" Enable preliminary SMTPUTF8 support for the protocols described -in RFC 6531..6533. +in RFC 6531, RFC 6532, and RFC 6533. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. @@ -465,6 +467,12 @@ Available in Postfix 3.5 and later: .IP "\fBinfo_log_address_format (external)\fR" The email address form that will be used in non\-debug logging (info, warning, etc.). +.PP +Available in Postfix 3.9 and later: +.IP "\fBforce_mime_input_conversion (no)\fR" +Convert body content that claims to be 8\-bit into quoted\-printable, +before header_checks, body_checks, Milters, and before after\-queue +content filters. .SH "FILES" .na .nf diff --git a/man/man8/dnsblog.8 b/man/man8/dnsblog.8 index bf55548..6c6cef3 100644 --- a/man/man8/dnsblog.8 +++ b/man/man8/dnsblog.8 @@ -55,7 +55,8 @@ configuration files. How much time a Postfix daemon process may take to handle a request before it is terminated by a built\-in watchdog timer. .IP "\fBpostscreen_dnsbl_sites (empty)\fR" -Optional list of DNS allow/denylist domains, filters and weight +Optional list of patterns with DNS allow/denylist domains, filters +and weight factors. .IP "\fBipc_timeout (3600s)\fR" The time limit for sending or receiving information over an internal diff --git a/man/man8/local.8 b/man/man8/local.8 index ca9c6c8..84736cb 100644 --- a/man/man8/local.8 +++ b/man/man8/local.8 @@ -223,27 +223,30 @@ are replaced with underscores. The list of acceptable characters is specified with the \fBcommand_expansion_filter\fR configuration parameter. .IP \fBSHELL\fR -The recipient user's login shell. +The envelope recipient user's login shell. .IP \fBHOME\fR -The recipient user's home directory. +The envelope recipient user's home directory. .IP \fBUSER\fR -The bare recipient name. +The bare envelope recipient name. .IP \fBEXTENSION\fR -The optional recipient address extension. +The optional envelope recipient address extension. .IP \fBDOMAIN\fR -The recipient address domain part. +The envelope recipient address domain part. .IP \fBLOGNAME\fR -The bare recipient name. +The bare envelope recipient name. .IP \fBLOCAL\fR -The entire recipient address localpart (text to the left of the -rightmost @ character). +The entire envelope recipient address localpart (text to +the left of the rightmost @ character). .IP \fBORIGINAL_RECIPIENT\fR -The entire recipient address, before any address rewriting -or aliasing (Postfix 2.5 and later). +The entire envelope recipient address, before any address +rewriting or aliasing (Postfix 2.5 and later). .IP \fBRECIPIENT\fR -The entire recipient address. +The entire envelope recipient address. .IP \fBSENDER\fR -The entire sender address. +The entire envelope sender address. +.IP \fBENVID\fR +The optional RFC 3461 envelope ID. Available as of Postfix +3.9. .PP Additional remote client information is made available via the following environment variables: @@ -449,7 +452,9 @@ mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport, and luser_relay. .IP "\fBalias_maps (see 'postconf -d' output)\fR" -The alias databases that are used for \fBlocal\fR(8) delivery. +Optional lookup tables with aliases that apply only to \fBlocal\fR(8) +recipients; this is unlike virtual_alias_maps that apply to all +recipients: \fBlocal\fR(8), virtual, and remote. .IP "\fBforward_path (see 'postconf -d' output)\fR" The \fBlocal\fR(8) delivery agent search list for finding a .forward file with user\-specified delivery methods. diff --git a/man/man8/master.8 b/man/man8/master.8 index 8c37de4..87fd648 100644 --- a/man/man8/master.8 +++ b/man/man8/master.8 @@ -151,13 +151,13 @@ The directory with Postfix support programs and daemon programs. The external command to execute when a Postfix daemon program is invoked with the \-D option. .IP "\fBinet_interfaces (all)\fR" -The network interface addresses that this mail system receives -mail on. -.IP "\fBinet_protocols (see 'postconf -d output')\fR" +The local network interface addresses that this mail system +receives mail on. +.IP "\fBinet_protocols (see 'postconf -d' output)\fR" The Internet protocols Postfix will attempt to use when making or accepting connections. .IP "\fBimport_environment (see 'postconf -d' output)\fR" -The list of environment parameters that a privileged Postfix +The list of environment variables that a privileged Postfix process will import from a non\-Postfix parent process, or name=value environment overrides. .IP "\fBmail_owner (postfix)\fR" diff --git a/man/man8/pipe.8 b/man/man8/pipe.8 index 8e54eaf..efb9e0e 100644 --- a/man/man8/pipe.8 +++ b/man/man8/pipe.8 @@ -240,6 +240,11 @@ the domain is \fIdomain\fR. This information is modified by the \fBh\fR flag for case folding. .sp This feature is available as of Postfix 2.5. +.IP \fB${envid}\fR +This macro expands to the RFC 3461 envelope ID if available, +otherwise the empty string. +.sp +This feature is available as of Postfix 3.9. .IP \fB${extension}\fR This macro expands to the extension part of a recipient address. For example, with an address \fIuser+foo@domain\fR the extension is diff --git a/man/man8/postlogd.8 b/man/man8/postlogd.8 index 9168a34..aeb95c7 100644 --- a/man/man8/postlogd.8 +++ b/man/man8/postlogd.8 @@ -41,10 +41,10 @@ set this permission on programs other than \fBpostdrop\fR(1), .nf .ad .fi -Changes to \fBmain.cf\fR are picked up automatically, as -\fBpostlogd\fR(8) processes run for only a limited amount -of time. Use the command "\fBpostfix reload\fR" to speed -up a change. +Changes to \fBmain.cf\fR are not picked up automatically, +because \fBpostlogd\fR(8) terminates only after reaching +the \fBmax_idle\fR time limit. +Use the command "\fBpostfix reload\fR" to speed up a change. The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. @@ -66,6 +66,12 @@ The master.cf service name of a Postfix daemon process. .IP "\fBpostlogd_watchdog_timeout (10s)\fR" How much time a \fBpostlogd\fR(8) process may take to process a request before it is terminated by a built\-in watchdog timer. +.PP +Available in Postfix 3.9 and later: +.IP "\fBmaillog_file_permissions (0600)\fR" +The file access permissions that will be set when the file +$maillog_file is created for the first time, or when the file is +created after an existing file is rotated. .SH "SEE ALSO" .na .nf diff --git a/man/man8/postscreen.8 b/man/man8/postscreen.8 index 556a865..0231b0a 100644 --- a/man/man8/postscreen.8 +++ b/man/man8/postscreen.8 @@ -323,25 +323,29 @@ Persistent storage for the \fBpostscreen\fR(8) server decisions. The amount of time that \fBpostscreen\fR(8) will cache an expired temporary allowlist entry before it is removed. .IP "\fBpostscreen_bare_newline_ttl (30d)\fR" -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful "bare newline" SMTP protocol test. +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a "bare newline" SMTP protocol test, before it +address is required to pass that test again. .IP "\fBpostscreen_dnsbl_max_ttl (${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)\fR" -The maximum amount of time that \fBpostscreen\fR(8) will use the -result from a successful DNS\-based reputation test before a -client IP address is required to pass that test again. +The maximum amount of time that \fBpostscreen\fR(8) remembers that a +client IP address passed a DNS\-based reputation test, before it is +required to pass that test again. .IP "\fBpostscreen_dnsbl_min_ttl (60s)\fR" -The minimum amount of time that \fBpostscreen\fR(8) will use the -result from a successful DNS\-based reputation test before a -client IP address is required to pass that test again. +The minimum amount of time that \fBpostscreen\fR(8) remembers that a +client IP address passed a DNS\-based reputation test, before it +is required to pass that test again. .IP "\fBpostscreen_greet_ttl (1d)\fR" -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful PREGREET test. +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a PREGREET test, before it is required to pass +that test again. .IP "\fBpostscreen_non_smtp_command_ttl (30d)\fR" -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful "non_smtp_command" SMTP protocol test. +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a "non_smtp_command" SMTP protocol test, before +it is required to pass that test again. .IP "\fBpostscreen_pipelining_ttl (30d)\fR" -The amount of time that \fBpostscreen\fR(8) will use the result from -a successful "pipelining" SMTP protocol test. +The amount of time that \fBpostscreen\fR(8) remembers that a client +IP address passed a "pipelining" SMTP protocol test, before it is +required to pass that test again. .SH "RESOURCE CONTROLS" .na .nf diff --git a/man/man8/proxymap.8 b/man/man8/proxymap.8 index e734a2b..ff0d759 100644 --- a/man/man8/proxymap.8 +++ b/man/man8/proxymap.8 @@ -43,7 +43,7 @@ proxymap server processes. .IP \(bu To provide single\-updater functionality for lookup tables that do not reliably support multiple writers (i.e. all -file\-based tables). +file\-based tables that are not based on \fBlmdb\fR). .PP The \fBproxymap\fR(8) server implements the following requests: .IP "\fBopen\fR \fImaptype:mapname flags\fR" diff --git a/man/man8/qmgr.8 b/man/man8/qmgr.8 index a24af71..ca1fd4c 100644 --- a/man/man8/qmgr.8 +++ b/man/man8/qmgr.8 @@ -234,7 +234,7 @@ A transport\-specific override for the default_recipient_refill_limit parameter value, where \fItransport\fR is the master.cf name of the message delivery transport. .IP "\fBdefault_recipient_refill_delay (5s)\fR" -The default per\-transport maximum delay between recipients refills. +The default per\-transport maximum delay between refilling recipients. .IP "\fBtransport_recipient_refill_delay ($default_recipient_refill_delay)\fR" A transport\-specific override for the default_recipient_refill_delay parameter value, where \fItransport\fR is the master.cf name of diff --git a/man/man8/qmqpd.8 b/man/man8/qmqpd.8 index 9ee6267..0f0a82b 100644 --- a/man/man8/qmqpd.8 +++ b/man/man8/qmqpd.8 @@ -75,7 +75,7 @@ filtering, or address mapping. Preliminary SMTPUTF8 support is introduced with Postfix 3.0. .IP "\fBsmtputf8_enable (yes)\fR" Enable preliminary SMTPUTF8 support for the protocols described -in RFC 6531..6533. +in RFC 6531, RFC 6532, and RFC 6533. .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" Detect that a message requires SMTPUTF8 support for the specified mail origin classes. diff --git a/man/man8/smtp.8 b/man/man8/smtp.8 index e53a377..0145350 100644 --- a/man/man8/smtp.8 +++ b/man/man8/smtp.8 @@ -1,14 +1,16 @@ -.TH SMTP 8 +.TH SMTP, LMTP 8 .ad .fi .SH NAME -smtp +smtp, lmtp \- Postfix SMTP+LMTP client .SH "SYNOPSIS" .na .nf \fBsmtp\fR [generic Postfix daemon options] [flags=DORX] + +\fBlmtp\fR [generic Postfix daemon options] [flags=DORX] .SH DESCRIPTION .ad .fi @@ -17,7 +19,9 @@ delivery protocols. It processes message delivery requests from the queue manager. Each request specifies a queue file, a sender address, a domain or host to deliver to, and recipient information. This program expects to be run from the \fBmaster\fR(8) process -manager. +manager. The process name, \fBsmtp\fR or \fBlmtp\fR, controls +the protocol, and the names of the configuration parameters +that will be used. The SMTP+LMTP client updates the queue file and marks recipients as finished, or it informs the queue manager that delivery should @@ -25,13 +29,9 @@ be tried again at a later time. Delivery status reports are sent to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as appropriate. -The SMTP+LMTP client looks up a list of mail exchanger addresses for -the destination host, sorts the list by preference, and connects -to each listed address until it finds a server that responds. - -When a server is not reachable, or when mail delivery fails due -to a recoverable error condition, the SMTP+LMTP client will try to -deliver the mail to an alternate host. +The server lookup strategy is different for SMTP and LMTP, +as described in the sections "SMTP SERVER LOOKUP" and "LMTP +SERVER LOOKUP". After a successful mail transaction, a connection may be saved to the \fBscache\fR(8) connection cache server, so that it @@ -41,48 +41,62 @@ By default, connection caching is enabled temporarily for destinations that have a high volume of mail in the active queue. Connection caching can be enabled permanently for specific destinations. -.SH "SMTP DESTINATION SYNTAX" +.SH "SMTP SERVER LOOKUP" .na .nf .ad .fi -The Postfix SMTP+LMTP client supports multiple destinations +The Postfix SMTP client supports multiple destinations separated by comma or whitespace (Postfix 3.5 and later). +Each destination is tried in the specified order. + SMTP destinations have the following form: .IP \fIdomainname\fR -.IP \fIdomainname\fR:\fIport\fR +.IP \fIdomainname\fR:\fIservice\fR Look up the mail exchangers for the specified domain, and -connect to the specified port (default: \fBsmtp\fR). +connect to the specified service (default: \fBsmtp\fR). +Optionally, mail exchangers may be looked up with SRV queries +instead of MX; this requires that \fIservice\fR is given +in symbolic form. .IP [\fIhostname\fR] -.IP [\fIhostname\fR]:\fIport\fR -Look up the address(es) of the specified host, and connect to -the specified port (default: \fBsmtp\fR). +.IP [\fIhostname\fR]:\fIservice\fR +Look up the address(es) for the specified host, and connect to +the specified service (default: \fBsmtp\fR). .IP [\fIaddress\fR] -.IP [\fIaddress\fR]:\fIport\fR +.IP [\fIaddress\fR]:\fIservice\fR Connect to the host at the specified address, and connect -to the specified port (default: \fBsmtp\fR). An IPv6 address +to the specified service (default: \fBsmtp\fR). An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. -.SH "LMTP DESTINATION SYNTAX" +.SH "LMTP SERVER LOOKUP" .na .nf .ad .fi -The Postfix SMTP+LMTP client supports multiple destinations +The Postfix LMTP client supports multiple destinations separated by comma or whitespace (Postfix 3.5 and later). +Each destination is tried in the specified order. + LMTP destinations have the following form: .IP \fBunix\fR:\fIpathname\fR Connect to the local UNIX\-domain server that is bound to the specified \fIpathname\fR. If the process runs chrooted, an absolute pathname is interpreted relative to the Postfix queue directory. +.IP \fBinet\fR:\fIdomainname\fR +.IP \fBinet\fR:\fIdomainname\fR:\fIservice\fR +Look up the LMTP servers for the specified domain and service +(default: \fBlmtp\fR). +This form is supported when SRV lookups are enabled, and +requires that \fIservice\fR is in symbolic form. .IP \fBinet\fR:\fIhostname\fR -.IP \fBinet\fR:\fIhostname\fR:\fIport\fR +.IP \fBinet\fR:\fIhostname\fR:\fIservice\fR +Look up the address(es) for the specified host, and connect to +the specified service (default: \fBlmtp\fR). When SRV lookups +are enabled, use the form \fB[\fIhostname\fB]\fR to force +address lookups. .IP \fBinet\fR:[\fIaddress\fR] -.IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR -Connect to the specified TCP port on the specified local or -remote host. If no port is specified, connect to the port defined as -\fBlmtp\fR in \fBservices\fR(4). -If no such service is found, the \fBlmtp_tcp_port\fR configuration -parameter (default value of 24) will be used. +.IP \fBinet\fR:[\fIaddress\fR]:\fIservice\fR +Connect to the specified local or remote host and service +(default: \fBlmtp\fR). An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. .SH "SINGLE-RECIPIENT DELIVERY" .na @@ -146,6 +160,8 @@ This feature is available as of Postfix 3.5. .SH "SECURITY" .na .nf +.ad +.fi The SMTP+LMTP client is moderately security\-sensitive. It talks to SMTP or LMTP servers and to DNS servers on the network. The SMTP+LMTP client can be run chrooted at fixed @@ -199,11 +215,10 @@ address and TCP port. .nf .ad .fi -Before Postfix version 2.3, the LMTP client is a separate -program that implements only a subset of the functionality -available with SMTP: there is no support for TLS, and -connections are cached in\-process, making it ineffective -when the client is used for multiple domains. +Postfix versions 2.3 and later implement the SMTP and LMTP +client with the same program, and choose the protocol and +configuration parameters based on the process name, \fBsmtp\fR +or \fBlmtp\fR. Most smtp_\fIxxx\fR configuration parameters have an lmtp_\fIxxx\fR "mirror" parameter for the equivalent LMTP @@ -464,6 +479,11 @@ Available in Postfix version 2.9 and later: .IP "\fBsmtp_send_dummy_mail_auth (no)\fR" Whether or not to append the "AUTH=<>" option to the MAIL FROM command in SASL\-authenticated SMTP sessions. +.PP +Available in Postfix version 3.9 and later: +.IP "\fBsmtp_sasl_password_result_delimiter (:)\fR" +The delimiter between username and password in sasl_passwd_maps lookup +results. .SH "STARTTLS SUPPORT CONTROLS" .na .nf @@ -566,7 +586,7 @@ The message digest algorithm used to construct remote SMTP server certificate fingerprints. .PP Available in Postfix version 2.6 and later: -.IP "\fBsmtp_tls_protocols (see postconf -d output)\fR" +.IP "\fBsmtp_tls_protocols (see 'postconf -d' output)\fR" TLS protocols that the Postfix SMTP client will use with opportunistic TLS encryption. .IP "\fBsmtp_tls_ciphers (medium)\fR" @@ -647,6 +667,11 @@ Optional configuration file with baseline OpenSSL settings. .IP "\fBtls_config_name (empty)\fR" The application name passed by Postfix to OpenSSL library initialization functions. +.PP +Available in Postfix version 3.9 and later: +.IP "\fBsmtp_tls_enable_rpk (no)\fR" +Request that remote SMTP servers send an RFC7250 raw public key +instead of an X.509 certificate. .SH "OBSOLETE STARTTLS CONTROLS" .na .nf @@ -843,9 +868,9 @@ sub\-second delay values. .IP "\fBdisable_dns_lookups (no)\fR" Disable DNS lookups in the Postfix SMTP and LMTP clients. .IP "\fBinet_interfaces (all)\fR" -The local network interface addresses that this mail system receives -mail on. -.IP "\fBinet_protocols (see 'postconf -d output')\fR" +The local network interface addresses that this mail system +receives mail on. +.IP "\fBinet_protocols (see 'postconf -d' output)\fR" The Internet protocols Postfix will attempt to use when making or accepting connections. .IP "\fBipc_timeout (3600s)\fR" diff --git a/man/man8/smtpd.8 b/man/man8/smtpd.8 index 6f72084..4569f1f 100644 --- a/man/man8/smtpd.8 +++ b/man/man8/smtpd.8 @@ -502,7 +502,7 @@ fingerprints or public key fingerprints (Postfix 2.9 and later) for \fBcheck_ccert_access\fR and \fBpermit_tls_clientcerts\fR. .PP Available in Postfix version 2.6 and later: -.IP "\fBsmtpd_tls_protocols (see postconf -d output)\fR" +.IP "\fBsmtpd_tls_protocols (see 'postconf -d' output)\fR" TLS protocols accepted by the Postfix SMTP server with opportunistic TLS encryption. .IP "\fBsmtpd_tls_ciphers (medium)\fR" @@ -571,6 +571,12 @@ Optional configuration file with baseline OpenSSL settings. .IP "\fBtls_config_name (empty)\fR" The application name passed by Postfix to OpenSSL library initialization functions. +.PP +Available in Postfix version 3.9 and later: +.IP "\fBsmtpd_tls_enable_rpk (no)\fR" +Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking for or requiring client +authentication. .SH "OBSOLETE STARTTLS CONTROLS" .na .nf @@ -706,12 +712,12 @@ Parameters concerning known/unknown local recipients: The list of domains that are delivered via the $local_transport mail delivery transport. .IP "\fBinet_interfaces (all)\fR" -The local network interface addresses that this mail system receives -mail on. +The local network interface addresses that this mail system +receives mail on. .IP "\fBproxy_interfaces (empty)\fR" The remote network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit. -.IP "\fBinet_protocols (see 'postconf -d output')\fR" +.IP "\fBinet_protocols (see 'postconf -d' output)\fR" The Internet protocols Postfix will attempt to use when making or accepting connections. .IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR" @@ -742,8 +748,9 @@ Postfix is the final destination for the specified list of virtual alias domains, that is, domains for which all addresses are aliased to addresses in other local or remote domains. .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" -Optional lookup tables that alias specific mail addresses or domains -to other local or remote addresses. +Optional lookup tables with aliases that apply to all recipients: +\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +only to \fBlocal\fR(8) recipients. .IP "\fBunknown_virtual_alias_reject_code (550)\fR" The Postfix SMTP server reply code when a recipient address matches $virtual_alias_domains, and $virtual_alias_maps specifies a list @@ -863,7 +870,7 @@ Disconnect remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. .PP Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: -.IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR" +.IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: normalize)\fR" Reject or restrict input lines from an SMTP client that end in instead of the standard . .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR" diff --git a/man/man8/tlsproxy.8 b/man/man8/tlsproxy.8 index 6913b7b..4677dc4 100644 --- a/man/man8/tlsproxy.8 +++ b/man/man8/tlsproxy.8 @@ -255,6 +255,12 @@ parameters smtpd_use_tls and smtpd_enforce_tls. .IP "\fBtlsproxy_tls_chain_files ($smtpd_tls_chain_files)\fR" Files with the Postfix \fBtlsproxy\fR(8) server keys and certificate chains in PEM format. +.PP +Available in Postfix version 3.9 and later: +.IP "\fBtlsproxy_tls_enable_rpk ($smtpd_tls_enable_rpk)\fR" +Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking or requiring client +authentication. .SH "STARTTLS CLIENT CONTROLS" .na .nf diff --git a/man/man8/trivial-rewrite.8 b/man/man8/trivial-rewrite.8 index e41da71..f2c39fb 100644 --- a/man/man8/trivial-rewrite.8 +++ b/man/man8/trivial-rewrite.8 @@ -142,9 +142,10 @@ Enable the rewriting of "site!user" into "user@site". .PP Available in Postfix 2.2 and later: .IP "\fBremote_header_rewrite_domain (empty)\fR" -Don't rewrite message headers from remote clients at all when -this parameter is empty; otherwise, rewrite message headers and -append the specified domain name to incomplete addresses. +Rewrite or add message headers in mail from remote clients if +the remote_header_rewrite_domain parameter value is non\-empty, +updating incomplete addresses with the domain specified in the +remote_header_rewrite_domain parameter, and adding missing headers. .SH "ROUTING CONTROLS" .na .nf @@ -163,10 +164,12 @@ The default mail delivery transport and next\-hop destination for final delivery to domains listed with $virtual_mailbox_domains. .IP "\fBrelay_transport (relay)\fR" The default mail delivery transport and next\-hop destination for -remote delivery to domains listed with $relay_domains. +the relay domain address class: recipient domains that match +$relay_domains. .IP "\fBdefault_transport (smtp)\fR" The default mail delivery transport and next\-hop destination for -destinations that do not match $mydestination, $inet_interfaces, +the default domain class: recipient domains that do not match +$mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, or $relay_domains. .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR" @@ -174,8 +177,8 @@ A list of Postfix features where the pattern "example.com" also matches subdomains of example.com, instead of requiring an explicit ".example.com" pattern. .IP "\fBrelayhost (empty)\fR" -The next\-hop destination(s) for non\-local mail; overrides non\-local -domains in recipient addresses. +The next\-hop destination(s) for non\-local mail; takes precedence +over non\-local domains in recipient addresses. .IP "\fBtransport_maps (empty)\fR" Optional lookup tables with mappings from recipient address to (message delivery transport, next\-hop destination). diff --git a/mantools/check-see-postconf-d-output b/mantools/check-see-postconf-d-output new file mode 100755 index 0000000..d74c4f1 --- /dev/null +++ b/mantools/check-see-postconf-d-output @@ -0,0 +1,6 @@ +#!/bin/sh + +# check-see-postconf-d-output - find missing is misplaced quotes + +grep -r "see *'*postconf -d'* *output'*" proto html man | + grep -v "see 'postconf -d' output" diff --git a/mantools/check-snapshot-nonprod b/mantools/check-snapshot-nonprod new file mode 100755 index 0000000..e18f6aa --- /dev/null +++ b/mantools/check-snapshot-nonprod @@ -0,0 +1,13 @@ +#!/bin/sh + +version=$(basename $(env - pwd)) || exit 1 +case "$version" in +postfix-[0-9]*.[0-9]*.[0-9]*) + test -f conf/makedefs.out || { + echo "Error: no conf/makedefs.out" 1>&2; exit 1; } + grep 'CCARGS.*-DSNAPSHOT' conf/makedefs.out && { + echo "Error: stable release builds with -DSNAPSHOT" 1>&2, exit 1; } + grep 'CCARGS.*-DNONPROD' conf/makedefs.out && { + echo "Error: stable release builds with -DNONPROD" 1>&2, exit 1; } + ;; +esac diff --git a/mantools/dehtml b/mantools/dehtml index cc120de..9a3be6f 100755 --- a/mantools/dehtml +++ b/mantools/dehtml @@ -3,7 +3,7 @@ for i do case $i in - /*) lynx -dump file://localhost$i;; - *) lynx -dump file://localhost`pwd`/$i;; + /*) lynx -width=256 -dump file://localhost$i;; + *) lynx -width=256 -dump file://localhost`pwd`/$i;; esac -done +done | grep -v 'file://localhost/' diff --git a/mantools/postlink b/mantools/postlink index 89b0fa4..6ca24c6 100755 --- a/mantools/postlink +++ b/mantools/postlink @@ -169,6 +169,7 @@ while (<>) { s;\bdisable_dns_lookups\b;$&;g; s;\bdisable_mime_input_processing\b;$&;g; s;\bdisable_mime_output_conversion\b;$&;g; + s;\bforce_mime_input_conversion\b;$&;g; s;\bdisable_verp_bounces\b;$&;g; s;\bdisable_vrfy_command\b;$&;g; s;\bdont_remove\b;$&;g; @@ -231,6 +232,8 @@ while (<>) { s;\blmtp_min_data_rate\b;$&;g; s;\blmtp_reply_filter\b;$&;g; s;\blmtp_sasl_password_maps\b;$&;g; + s;\bsmtp_sasl_password_result_delimiter\b;$&;g; + s;\blmtp_sasl_password_result_delimiter\b;$&;g; s;\blmtp_send_dummy_mail_auth\b;$&;g; s;\blmtp_balance_inet_protocols\b;$&;g; s;\blmtp_sender_dependent_authentication\b;$&;g; @@ -273,6 +276,7 @@ while (<>) { s;\blmtp_tls_loglevel\b;$&;g; s;\blmtp_tls_session_cache_database\b;$&;g; s;\blmtp_tls_session_cache_timeout\b;$&;g; + s;\blmtp_tls_enable_rpk\b;$&;g; s;\blmtp_tls_wrappermode\b;$&;g; s;\blmtp_generic_maps\b;$&;g; s;\blmtp_pix_workaround_threshold_time\b;$&;g; @@ -699,6 +703,7 @@ while (<>) { s;\bsmtp_tls_block_early_mail_reply\b;$&;g; s;\bsmtp_tls_dane_insecure_mx_policy\b;$&;g; s;\bsmtp_tls_force_insecure_host_tlsa_lookup\b;$&;g; + s;\bsmtp_tls_enable_rpk\b;$&;g; s;\bsmtp_tls_wrappermode\b;$&;g; s;\bsmtp_use_tls\b;$&;g; s;\bsmtp_header_checks\b;$&;g; @@ -752,6 +757,7 @@ while (<>) { s;\bsmtpd_tls_ses[-]*\n*[ ]*sion_cache_database\b;$&;g; s;\bsmtpd_tls_ses[-]*\n*[ ]*sion_cache_timeout\b;$&;g; s;\bsmtpd_tls_always_issue_ses[-]*\n*[ ]*sion_ids\b;$&;g; + s;\bsmtpd_tls_enable_rpk\b;$&;g; s;\bsmtpd_tls_wrappermode\b;$&;g; s;\bsmtpd_use_tls\b;$&;g; s;\bsmtpd_reject_footer\b;$&;g; @@ -889,6 +895,7 @@ while (<>) { s/[]*lmdb[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*mas[-<\/bB>]*\n* *[]*ter[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*mem[-<\/bB>]*\n* *[]*cache[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; + s/[]*mongodb[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*mysql[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*nisplus[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*pcre[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; @@ -1124,6 +1131,7 @@ while (<>) { s;\btlsproxy_tls_protocols\b;$&;g; s;\btlsproxy_tls_req_ccert\b;$&;g; s;\btlsproxy_tls_security_level\b;$&;g; + s;\btlsproxy_tls_enable_rpk\b;$&;g; s;\btlsproxy_use_tls\b;$&;g; s;\btlsproxy_client_CAfile\b;$&;g; @@ -1160,6 +1168,7 @@ while (<>) { s;\bmail[-]*\n*[ ]*log_file_compressor\b;$&;g; s;\bmail[-]*\n*[ ]*log_file_prefixes\b;$&;g; s;\bmail[-]*\n*[ ]*log_file_rotate_suffix\b;$&;g; + s;\bmail[-]*\n*[ ]*log_file_permissions\b;$&;g; s;\bpostlog_service_name\b;$&;g; s;\bpostlogd_watchdog_timeout\b;$&;g; @@ -1228,6 +1237,8 @@ while (<>) { s/\b"*hold"* *queues*\b/$&<\/a>/g; s/\b("*hold"*),/$1<\/a>,/g; s/\b(postfix *tls)\b/$1<\/a>/g; + s/\b(local\s*aliasing)\b/$1<\/a>/g; + s/\b(virtual\s*aliasing)\b/$1<\/a>/g; # Hyperlink map types. @@ -1242,6 +1253,7 @@ while (<>) { s/\b(ldap[is]?):/$1<\/a>:/g; s/\b(lmdb):/$1<\/a>:/g; s/\b(memcache):/$1<\/a>:/g; + s/\b(mongodb):/$1<\/a>:/g; s/\b(mysql):/$1<\/a>:/g; s/\b(nisplus):/$1<\/a>:/g; s/\b(pcre):/$1<\/a>:/g; diff --git a/postfix-install b/postfix-install index f6780e7..563ee27 100644 --- a/postfix-install +++ b/postfix-install @@ -176,6 +176,7 @@ # post-install(1) post-installation procedure # FILES # $config_directory/main.cf, Postfix installation configuration. +# $config_directory/makedefs.out, Postfix 'make makefiles' options. # $meta_directory/postfix-files, installation control file. # $config_directory/install.cf, obsolete configuration file. # LICENSE @@ -192,6 +193,10 @@ # Google, Inc. # 111 8th Avenue # New York, NY 10011, USA +# +# Wietse Venema +# porcupine.org +# Amawalk, NY 10501, USA #-- # Initialize. @@ -520,7 +525,7 @@ test -f $CONFIG_DIRECTORY/main.cf && { case "$junk" in "") eval unset $name;; esac - eval : \${$name=\`bin/postconf -c $CONFIG_DIRECTORY -hx $name\`} || + eval : \${$name=\`bin/postconf -qc $CONFIG_DIRECTORY -hx $name\`} || exit 1 done } @@ -861,7 +866,7 @@ do esac done -bin/postconf -c $CONFIG_DIRECTORY -e \ +bin/postconf -qc $CONFIG_DIRECTORY -e \ "daemon_directory = $daemon_directory" \ "data_directory = $data_directory" \ "command_directory = $command_directory" \ diff --git a/proto/ADDRESS_CLASS_README.html b/proto/ADDRESS_CLASS_README.html index 7a30535..5deac11 100644 --- a/proto/ADDRESS_CLASS_README.html +++ b/proto/ADDRESS_CLASS_README.html @@ -52,20 +52,25 @@ address classes are very important for the operation of Postfix.

      • The list of domains that are a member of that address -class: for example, all local domains, or all relay domains.

        +class.

        + +

        Examples: all local domains, or all relay domains.

        + +
      • The default delivery transport for domains in that address +class.

        + +

        Examples: local_transport or relay_transport (these point +to services defined in master.cf).

        -
      • The default delivery transport for that address class. For -example, the local, -virtual or relay delivery transport (delivery transports are defined -in master.cf). This helps to keep Postfix configurations simple, -by avoiding the need for explicit routing information in transport -maps.

        +

        Benefit: this avoids the need for explicit routing information +in transport maps.

      • The list of valid recipient addresses for that address -class. The Postfix SMTP server rejects invalid recipients with -"User unknown in <name of address class here> table". This -helps to keep the Postfix queue free of undeliverable MAILER-DAEMON -messages.

        +class.

        + +

        Benefit: the Postfix SMTP server rejects an invalid recipient +with "User unknown in <name of address class> table", and +avoids sending a MAILER-DAEMON message with backscatter spam.

      @@ -92,12 +97,12 @@ This domain class also includes mail for user@[ipaddress] when the IP address is listed with the inet_interfaces or proxy_interfaces parameters.

      -
    • Valid recipient addresses are listed with the local_recipient_maps -parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP -server rejects invalid recipients with "User unknown in local -recipient table". If the local_recipient_maps parameter value is -empty, then the Postfix SMTP server accepts any address in the -local domain class.

      +
    • Valid recipient addresses for those domains are +listed with the local_recipient_maps parameter, as described in +LOCAL_RECIPIENT_README. The Postfix SMTP server rejects invalid recipients +with "User unknown in local recipient table". If the local_recipient_maps +parameter value is empty, then the Postfix SMTP server accepts any +address in the local domain class.

    • The mail delivery transport is specified with the local_transport parameter. The default value is local:$myhostname @@ -111,21 +116,25 @@ class.

      • Purpose: hosted domains where each recipient address is -aliased to an address in a different domain, for example, a local -UNIX system account or a remote address. A +aliased to an address in a different domain class, for example, a +local UNIX system account or a remote address. A virtual alias example is given in the VIRTUAL_README file.

      • Domain names are listed in virtual_alias_domains. The default value is $virtual_alias_maps for Postfix 1.1 compatibility.

        -
      • Valid recipient addresses are listed with the virtual_alias_maps -parameter. The Postfix SMTP server rejects invalid recipients with -"User unknown in virtual alias table". The default value is -$virtual_maps for Postfix 1.1 compatibility.

        +
      • Valid recipient addresses for those domains are listed with the +virtual_alias_maps parameter. The Postfix SMTP server rejects invalid +recipients with "User unknown in virtual alias table". The default +value is $virtual_maps for Postfix 1.1 compatibility.

        -
      • There is no mail delivery transport parameter. Every -address must be aliased to an address in some other domain.

        +

        Note: for historical reasons, virtual_alias_maps +apply to recipients in all domain classes, not only the virtual +alias domain class.

        + +
      • There is no configurable mail delivery transport. Every +address must be aliased to an address in some other domain class.

      @@ -136,18 +145,19 @@ class.

    • Purpose: final delivery for hosted domains where each recipient address can have its own mailbox, and where users do not -need to have a UNIX system account. A virtual mailbox example is +need to have a UNIX system account. A virtual mailbox example is given in the VIRTUAL_README file.

    • Domain names are listed with the virtual_mailbox_domains parameter. The default value is $virtual_mailbox_maps for Postfix 1.1 compatibility.

      -
    • Valid recipient addresses are listed with the virtual_mailbox_maps -parameter. The Postfix SMTP server rejects invalid recipients with -"User unknown in virtual mailbox table". If this parameter value -is empty, the Postfix SMTP server accepts all recipients for domains -listed in $virtual_mailbox_domains.

      +
    • Valid recipient addresses for those domains are listed +with the virtual_mailbox_maps parameter. The Postfix SMTP server +rejects invalid recipients with "User unknown in virtual mailbox +table". If this parameter value is empty, the Postfix SMTP server +accepts all recipients for domains listed in $virtual_mailbox_domains. +

    • The mail delivery transport is specified with the virtual_transport parameter. The default value is virtual @@ -169,11 +179,12 @@ file.

    • Domain names are listed with the relay_domains parameter.

      -
    • Valid recipient addresses are listed with the relay_recipient_maps -parameter. The Postfix SMTP server rejects invalid recipients with -"User unknown in relay recipient table". If this parameter value -is empty, the Postfix SMTP server accepts all recipients for domains -listed with the relay_domains parameter.

      +
    • Valid recipient addresses for those domains are listed +with the relay_recipient_maps parameter. The Postfix SMTP server +rejects invalid recipients with "User unknown in relay recipient +table". If this parameter value is empty, the Postfix SMTP server +accepts all recipients for domains listed with the relay_domains +parameter.

    • The mail delivery transport is specified with the relay_transport parameter. The default value is relay which diff --git a/proto/ADDRESS_REWRITING_README.html b/proto/ADDRESS_REWRITING_README.html index c858410..631a7d3 100644 --- a/proto/ADDRESS_REWRITING_README.html +++ b/proto/ADDRESS_REWRITING_README.html @@ -94,9 +94,7 @@ as invalid

    • Address manipulation Scope Daemon Global turn-on control Selective -turn-off control
      Daemon Turn-on controls +Turn-off controls
      Rewrite addresses to standard form all mail trivial-
      rewrite(8)
      cleanup(8) < nowrap> all mail cleanup(8) virtual_alias_maps receive_override_options
      Resolve address to destination - all mail trivial-
      rewrite(8)
      none none
      Mail transport switch all mail trivial-
      rewrite(8)
      -transport_maps none
      Resolve address to (transport, next-hop +destination) all mail +trivial-
      rewrite(8)
      local_transport, virtual_transport, +relay_transport, default_transport, relayhost, +sender_dependent_relayhost_maps, sender_dependent_default_transport_maps + content_filter
      Relocated users table all mail trivial-
      rewrite(8)
      @@ -774,6 +771,11 @@ may be a more appropriate vehicle. See the VIRTUAL for an overview of methods to host virtual domains with Postfix.

      +

      Note: virtual aliasing (virtual_alias_maps) applies to all +recipients: local(8), virtual, and remote. +This is unlike local aliasing (alias_maps) which applies only to +local(8) recipients.

      +

      Virtual aliasing is disabled by default. To enable, edit the virtual_alias_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or @@ -792,7 +794,7 @@ commas.

      Addresses found in virtual alias maps are subjected to another -iteration of virtual aliasing, but are not subjected to canonical +iteration of virtual aliasing, but are not subjected to canonical mapping, in order to avoid loops.

      For static mappings as shown above, lookup tables such as hash:, @@ -833,9 +835,8 @@ manager delegates the more complex address manipulations to the

      Logged with compatibility_level < 2:

      Logged with compatibility_level < 3.6:

      @@ -241,6 +241,48 @@ administrator should make the backwards-compatible setting +

      Using backwards-compatible default +setting smtputf8_enable=no

      + +

      The smtputf8_enable default value has changed from "no" to "yes". +With the new "yes" setting, the Postfix SMTP server rejects non-ASCII +addresses from clients that don't request SMTPUTF8 support, after +Postfix is updated from an older version. The backwards-compatibility +safety net is designed to prevent such surprises.

      + +

      As long as the smtputf8_enable parameter is left at its implicit +default value, and the compatibility_level setting is +less than 1, Postfix logs a warning each time an SMTP command uses a +non-ASCII address localpart without requesting SMTPUTF8 support:

      + +
      +
      +postfix/smtpd[27560]: using backwards-compatible default setting
      +    smtputf8_enable=no to accept non-ASCII sender address
      +    "??@example.org" from localhost[127.0.0.1]
      +
      +
      + +
      +
      +postfix/smtpd[27560]: using backwards-compatible default setting
      +    smtputf8_enable=no to accept non-ASCII recipient address
      +    "??@example.com" from localhost[127.0.0.1]
      +
      +
      + +

      If the address should not be rejected, and the client cannot +be updated to use SMTPUTF8, then the system administrator should +make the backwards-compatible setting "smtputf8_enable = no" permanent +in main.cf: + +

      +
      +# postconf smtputf8_enable=no
      +# postfix reload
      +
      +
      +

      Using backwards-compatible default setting mynetworks_style=subnet

      @@ -352,48 +394,6 @@ administrator should make the backwards-compatible setting

      Instead of $mydestination, it may be better to specify an explicit list of domain names.

      -

      Using backwards-compatible default -setting smtputf8_enable=no

      - -

      The smtputf8_enable default value has changed from "no" to "yes". -With the new "yes" setting, the Postfix SMTP server rejects non-ASCII -addresses from clients that don't request SMTPUTF8 support, after -Postfix is updated from an older version. The backwards-compatibility -safety net is designed to prevent such surprises.

      - -

      As long as the smtputf8_enable parameter is left at its implicit -default value, and the compatibility_level setting is -less than 1, Postfix logs a warning each time an SMTP command uses a -non-ASCII address localpart without requesting SMTPUTF8 support:

      - -
      -
      -postfix/smtpd[27560]: using backwards-compatible default setting
      -    smtputf8_enable=no to accept non-ASCII sender address
      -    "??@example.org" from localhost[127.0.0.1]
      -
      -
      - -
      -
      -postfix/smtpd[27560]: using backwards-compatible default setting
      -    smtputf8_enable=no to accept non-ASCII recipient address
      -    "??@example.com" from localhost[127.0.0.1]
      -
      -
      - -

      If the address should not be rejected, and the client cannot -be updated to use SMTPUTF8, then the system administrator should -make the backwards-compatible setting "smtputf8_enable = no" permanent -in main.cf: - -

      -
      -# postconf smtputf8_enable=no
      -# postfix reload
      -
      -
      -

      Using backwards-compatible default setting smtpd_tls_fingerprint_digest=md5

      diff --git a/html/DATABASE_README.html b/html/DATABASE_README.html index e3b3c05..87941bc 100644 --- a/html/DATABASE_README.html +++ b/html/DATABASE_README.html @@ -56,10 +56,10 @@ documentation:

       /etc/postfix/main.cf:
      -    alias_maps = hash:/etc/postfix/aliases            (local aliasing)
      +    alias_maps = hash:/etc/postfix/aliases            (local aliasing)
           header_checks = regexp:/etc/postfix/header_checks (content filtering)
           transport_maps = hash:/etc/postfix/transport      (routing table)
      -    virtual_alias_maps = hash:/etc/postfix/virtual    (address rewriting)
      +    virtual_alias_maps = hash:/etc/postfix/virtual    (virtual aliasing)
       
      @@ -349,6 +349,11 @@ See lmdb_table(5) for details.
      Memcache database client. Configuration details are given in memcache_table(5).
      +
      mongodb (read-only)
      + +
      MongoDB database client. Configuration details are given in +mongodb_table(5), with examples in MONGODB_README.
      +
      mysql (read-only)
      MySQL database client. Configuration details are given in diff --git a/html/DEPRECATION_README.html b/html/DEPRECATION_README.html new file mode 100644 index 0000000..4729568 --- /dev/null +++ b/html/DEPRECATION_README.html @@ -0,0 +1,411 @@ + + + + + + +Postfix Replacements for Deprecated Features + + + + + + + + +

      Postfix +Replacements for Deprecated Features

      + +
      + +

      Purpose of this document

      + +

      This document describes Postfix features that are deprecated +(will be removed) or that have already been removed. It also has +tips for making an existing Postfix configuration more future-proof. +

      + +

      Overview:

      + + + +

      Why deprecate?

      + +

      Sometimes, a Postfix feature needs to be replaced with a different +one. To give an example:

      + +
        + +
      • The initial Postfix TLS implementation used multiple boolean +parameters: one parameter to enable opportunistic TLS (for example, +"smtp_enforce_tls = yes") and one parameter to enable mandatory TLS +(for example, "smtp_require_tls = yes").

        + +
      • As we added support more features such as fingerprint, +dane, and so on, we decided not to add more boolean parameters. +Instead we introduced one configuration parameter to select from +multiple deployment models (for example, smtp_tls_security_level = +may | encrypt | dane, etc...).

        + +
      + + + +

      Having both the "old" and "new" way to configure Postfix is +convenient for existing Postfix installations, because their +configuration does not break after an upgrade to a new version. +Unfortunately, there are also disadvantages. Having multiple ways +to do similar things is not only confusing for newcomers, it also +makes Postfix harder to change.

      + +

      Deprecation process

      + +

      The basic process steps are:

      + +
        + +
      1. Inform humans that a feature will be removed, and suggest +replacements, in logging and documentation.

        + +
      2. Remove the feature, and update logging and documentation.

        + +
      + +

      Disclaimer: it has taken 20 years for some features to be +removed. This past is not a guarantee for the future.

      + +

      Deprecated features

      + +

      The table summarizes removed or deprecated features and +replacements. Click on the "obsolete feature" name for a more +detailed description.

      + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Obsolete feature name Warning as
      of version +
      Removed
      in version
      Replacement
      disable_dns_lookups + 3.9 - smtp_dns_support_level
      xxx_use_tls 3.9 - +xxx_tls_security_level
      xxx_enforce_tls + 3.9 - xxx_tls_security_level
      xxx_per_site 3.9 - +xxx_policy_maps
      +smtpd_tls_dh1024_param_file 3.9 - do not specify (leave at default) +
      smtpd_tls_eecdh_grade + 3.9 - do not specify (leave at default)
      permit_mx_backup 3.9 - +relay_domains
      check_relay_domains + 2.2 3.9 permit_mynetworks, reject_unauth_destination
      reject_maps_rbl 2.1 3.9 +reject_rbl_client
      permit_naked_ip_address + 2.0 3.9 + permit_mynetworks, permit_sasl_authenticated
      + +
      + +

      Obsolete DNS on/off configuration +

      + +

      The postconf(1) command logs the following:

      + + + +

      Replace obsolete configuration with its replacement:

      + +
      + + + + + + + + + +
      Goal Obsolete configuration + Replacement configuration
      To disable DNS lookups in the Postfix SMTP/LMTP client + disable_dns_lookups = yes smtp_dns_support_level += disabled
      To enable DNS lookups in the Postfix SMTP/LMTP client +disable_dns_lookups = no +Leave smtp_dns_support_level at the implicit default which is empty, unless +you need a higher support level such as DNSSEC.
      + +
      + +

      Obsolete opportunistic TLS configuration +

      + +

      The postconf(1) command logs one of the following:

      + + + +

      There are similarly-named parameters and warnings for postscreen(8) +and tlsproxy(8), but those parameters should rarely be specified +by hand.

      + +

      Replace obsolete configuration with its replacement:

      + +
      + + + + + + + + + + +
      Goal Obsolete configuration Replacement configuration
      To turn off TLS xxx_use_tls = no xxx_security_level = none
      To turn on opportunistic TLS xxx_use_tls += yes xxx_security_level = may
      + +
      + +

      Obsolete mandatory TLS configuration +

      + +

      The postconf(1) command logs one of the following:

      + + + +

      There are similarly-named parameters and warnings for postscreen(8) +and tlsproxy(8), but those parameters should rarely be specified +by hand.

      + +

      Replace obsolete configuration with its replacement:

      + +
      + + + + + + + + + +
      Goal Obsolete configuration Replacement configuration
      To turn off mandatory TLS xxx_enforce_tls += no xxx_security_level = may
      To turn on mandatory TLS xxx_enforce_tls += yes xxx_security_level = encrypt
      + +
      + +

      Obsolete TLS policy table configuration +

      + +

      The postconf(1) command logs one of the following:

      + + + +

      There is similarly-named parameter and warning for tlsproxy(8), +but that parameter should rarely be specified by hand.

      + +

      Unfortunately, this is more than a name change: the table format +has changed too, as has the table search process. There is no simple +conversion of the obsolete form to its replacement.

      + +

      check_relay_domains

      + +

      Depending on the Postfix version, the Postfix SMTP daemon logs +following warning:

      + +
        + +
      • support for restriction "check_relay_domains" has been removed +in Postfix 3.9"; instead, specify "reject_unauth_destination" + +
      • support for restriction "check_relay_domains" will be removed +from Postfix; use "reject_unauth_destination" instead + +
      + +

      This feature was removed because it would relay based on the +client domain name, which is not robust.

      + +

      Recommended configuration to prevent an "open relay" problem +with the SMTP service on port 25: +

      + +
      +
      +main.cf:
      +    smtpd_recipient_restrictions = 
      +        permit_mynetworks, 
      +        permit_sasl_authenticated, 
      +        reject_unauth_destination
      +        ...other restrictions...
      +
      +
      + +

      Or equivalent in smtpd_relay_restrictions.

      + +

      permit_mx_backup

      + +

      The Postfix version 3.9 and later SMTP daemon logs the following +warning:

      + + + +

      This feature will be removed because it is too difficult to +configure recipient address validation, making Postfix a source of +backscatter bounces.

      + +

      To specify the domains that Postfix will provide MX backup +service for, see +Configuring Postfix as primary or backup MX host for a remote +site.

      + +

      reject_maps_rbl

      + +

      Depending on the Postfix version, the SMTP daemon logs one of +the following warnings:

      + +
        + +
      • support for restriction "reject_maps_rbl" has been removed in +Postfix 3.9"; instead, specify "reject_rbl_client domain-name" + +
      • support for restriction "reject_maps_rbl" will be removed from +Postfix; use "reject_rbl_client domain-name" instead + +
      + +

      This feature was replaced because "MAPS RBL" is the name of a +specific reputation service. The reject_rbl_client feature provides +a superset of the reject_maps_rbl functionality.

      + +

      Recommended configuration:

      + +
      +
      +main.cf:
      +    smtpd_recipient_restrictions =
      +        permit_mynetworks,
      +        permit_sasl_authenticated,
      +        reject_unauth_destination
      +        reject_rbl_client domain-name
      +        ...other restrictions...
      +
      +
      + +

      Where domain-name is the domain name of a DNS reputation service.

      + +

      permit_naked_ip_address

      + +

      Depending on the Postfix version, the SMTP daemon logs one of +the following warnings:

      + + + +

      This feature was removed because it was easy to get a false +match when smtpd_recipient_restrictions was intended to match a +remote SMTP client IP address.

      + +

      Recommended configuration:

      + +
      +
      +main.cf:
      +    smtpd_recipient_restrictions =
      +        permit_mynetworks,
      +        permit_sasl_authenticated,
      +        reject_unauth_destination
      +        reject_rbl_client domain-name
      +        ...other restrictions...
      +
      +
      + +

      That is, no restriction on HELO or EHLO syntax. Such restrictions +ar rarely useful nowadays. + + + + diff --git a/html/INSTALL.html b/html/INSTALL.html index 6cd70d1..94d78ba 100644 --- a/html/INSTALL.html +++ b/html/INSTALL.html @@ -605,6 +605,9 @@ describe how to build Postfix with support for optional features:

      LDAP database LDAP_README Postfix 1.0
      MongoDB database MONGODB_README Postfix +3.9
      MySQL database MYSQL_README Postfix 1.0
      - + @@ -340,13 +338,12 @@ sender_bcc_maps, recipient_bcc_maps - - - - - + + + diff --git a/proto/LOCAL_RECIPIENT_README.html b/proto/LOCAL_RECIPIENT_README.html index a06b81f..2cb3fb2 100644 --- a/proto/LOCAL_RECIPIENT_README.html +++ b/proto/LOCAL_RECIPIENT_README.html @@ -57,7 +57,8 @@ all names or addresses of local recipients. A recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local username or address is not listed in $local_recipient_maps, then the Postfix SMTP server will reject -the address with "User unknown in local recipient table".

      +the address with "User unknown in local recipient table". Other +Postfix interfaces may still accept an "unknown" recipient.

      The default setting, shown below, assumes that you use the default Postfix local(8) delivery agent for local delivery, where diff --git a/proto/MAILLOG_README.html b/proto/MAILLOG_README.html index da1c1a8..13c1091 100644 --- a/proto/MAILLOG_README.html +++ b/proto/MAILLOG_README.html @@ -63,10 +63,16 @@ Postfix version.

      /var/log/postfix.log. See also the "Logfile rotation" section below for logfile management.

      +

      In the example below, specifying maillog_file_permissions is +optional (Postfix 3.9 and later). The default value is 0600, i.e., +only the super-user can access the file; the value 0644 also +adds 'group' and 'other' read access.

      +
       # postfix stop
       # postconf maillog_file=/var/log/postfix.log
      +# postconf maillog_file_permissions=0644 # (Postfix 3.9 and later)
       # postfix start
       
      @@ -124,6 +130,10 @@ old logfile.

      program is configured with the maillog_file_compressor parameter (default: gzip).

      +
    • The next time it logs an event, postlogd(8) will create a +new logfile, with permissions specified with the maillog_file_permissions +parameter (default: 0600).

      +

      Notes:

      diff --git a/proto/MILTER_README.html b/proto/MILTER_README.html index d40d24c..9f9833b 100644 --- a/proto/MILTER_README.html +++ b/proto/MILTER_README.html @@ -630,7 +630,7 @@ main.cf: items separated by space or comma. There is one difference: clients

      The smtpd_milter_maps feature supports different Milter settings -for different client IP addresses. Lookup results override the the +for different client IP addresses. Lookup results override the global smtpd_milters setting, and have the same syntax. For example, to disable Milter settings for local address ranges:

      diff --git a/proto/MONGODB_README.html b/proto/MONGODB_README.html new file mode 100644 index 0000000..f5e1d5f --- /dev/null +++ b/proto/MONGODB_README.html @@ -0,0 +1,263 @@ + + + +Postfix MongoDB Howto + + + +

      Postfix MongoDB Howto

      +
      + +

      MongoDB Support in Postfix

      + +

      Postfix can use MongoDB as a source for any of its lookups: +aliases(5), virtual(5), canonical(5), etc. This allows you to keep +information for your mail service in a replicated noSQL database +with fine-grained access controls. By not storing it locally on the +mail server, the administrators can maintain it from anywhere, and +the users can control whatever bits of it you think appropriate. +You can have multiple mail servers using the same information, +without the hassle and delay of having to copy it to each.

      + +

      Topics covered in this document:

      + + + +

      Building Postfix with MongoDB support

      + +

      These instructions assume that you build Postfix from source +code as described in the INSTALL document. Some modification may +be required if you build Postfix from a vendor-specific source +package.

      + +

      The Postfix MongoDB client requires the mongo-c-driver +library. This can be built from source code from the +mongod-c project, or this can be installed as a binary package +from your OS distribution, typically named mongo-c-driver, +mongo-c-driver-devel or libmongoc-dev. +Installing the mongo-c-driver library may also install libbson +as a dependency.

      + +

      To build Postfix with mongodb map support, add to the CCARGS +environment variable the options -DHAS_MONGODB and -I for the +directory containing the mongodb headers, and specify the AUXLIBS_MONGODB +with the libmongoc and libbson libraries, for example:

      + +
      +
      +% make tidy
      +% make -f Makefile.init makefiles \
      +    CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
      +    -I/usr/include/libbson-1.0" \
      +    AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0"
      +
      +
      + +

      The 'make tidy' command is needed only if you have previously +built Postfix without MongoDB support.

      + +

      If your MongoDB shared library is in a directory that the RUN-TIME +linker does not know about, add a "-Wl,-R,/path/to/directory" option +after "-lbson-1.0". Then, just run 'make'.

      + +

      Configuring MongoDB lookups

      + +

      In order to use MongoDB lookups, define a MongoDB source as a +table lookup in main.cf, for example:

      + +
      +
      +alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf
      +
      +
      + +

      The file /etc/postfix/mongo-aliases.cf can specify a number of +parameters. For a complete description, see the mongodb_table(5) +manual page.

      + +

      Example: virtual(5) alias maps

      + +

      Here's a basic example for using MongoDB to look up virtual(5) +aliases. Assume that in main.cf, you have:

      + +
      +
      +virtual_alias_maps = hash:/etc/postfix/virtual_aliases, 
      +    proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf
      +
      +
      + +

      and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have:

      + +
      +
      +uri = mongodb+srv://user_name:password@some_server
      +dbname = mail
      +collection = mailbox
      +query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
      +result_attribute = username
      +
      +
      + +

      This example assumes mailbox names are stored in a MongoDB backend, +in a format like:

      + +
      +
      +{ "username": "user@example.com",
      +  "alias": [
      +    {"address": "admin@example.com"},
      +    {"address": "abuse@example.com"}
      +  ],
      +  "active": 1
      +}
      +
      +
      + +

      Upon receiving mail for "admin@example.com" that isn't found in the +/etc/postfix/virtual_aliases database, Postfix will search the +MongoDB server/cluster listening at port 27017 on some_server. It +will connect using the provided credentials, and search for any +entries whose username is, or alias field has "admin@example.com". +It will return the username attribute of those found, and build a +list of their email addresses.

      + +

      Notes:

      + +
        + +
      • As with projection (see below), the Postfix mongodb +client automatically removes the top-level '_id' field from a +result_attribute result.

      • + +
      • The Postfix mongodb client will only parse result fields +with data types UTF8, INT32, INT64 and ARRAY. Other fields will be +ignored, with a warning in the logs.

      • + +
      + +

      Example: Mailing lists

      + +

      When it comes to mailing lists, one way of implementing one would +be as below:

      + +
      +
      +{ "name": "dev@example.com", "active": 1, "address": 
      +  [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
      +
      +
      + +

      using the filter below, will result in a comma separated string +with all email addresses in this list.

      + +
      +
      +query_filter = {"name": "%s", "active": 1}
      +result_attribute = address
      +
      +
      + +

      Notes:

      + +
        + +
      • As with projection (see below), the Postfix mongodb +client automatically removes the top-level '_id' field from a +result_attribute result.

      • + +
      • The Postfix mongodb client will only parse result fields +with data types UTF8, INT32, INT64 and ARRAY. Other fields will be +ignored, with a warning in the logs.

      • + +
      + +

      Example: advanced projections

      + +

      This module also supports the use of more complex MongoDB +projections. There may be some use cases where operations such as +concatenation are necessary to be performed on the data retrieved +from the database. Although it is encouraged to keep the database +design simple enough so this is not necessary, postfix supports the +use of MongoDB projections to achieve the goal.

      + +

      Consider the example below:

      + +
      +
      +{ "username": "user@example.com",
      +  "local_part": "user",
      +  "domain": "example.com",
      +  "alias": [
      +    {"address": "admin@example.com"},
      +    {"address": "abuse@example.com"}
      +  ],
      +  "active": 1
      +}
      +
      +
      + +

      virtual_mailbox_maps can be created using below parameters in a +mongodb:/etc/postfix/mongo-virtual-mailboxes.cf file:

      + +
      +
      +uri = mongodb+srv://user_name:password@some_server
      +dbname = mail
      +collection = mailbox
      +query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
      +projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
      +
      +
      + +

      This will return 'example.com/user' path built from the database fields.

      + +

      A couple of considerations when using projections:

      + +
        + +
      • As with result_attribute, the Postfix mongodb client +automatically removes the top-level '_id' field from a projection +result.

      • + +
      • The Postfix mongodb client will only parse fields with data +types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, +with a warning in the logs. It is suggested to exclude any unnecessary +fields when using a projection.

      • + +
      + +

      Feedback

      + +

      If you have questions, send them to postfix-users@postfix.org. +Please include relevant information about your Postfix setup: +MongoDB-related output from postconf, which libraries you built +with, and such. If your question involves your database contents, +please include the applicable bits of some database entries.

      + +

      Credits

      + +
        + +
      • Stephan Ferraro (Aionda GmbH) implemented an early version of the +Postfix MongoDB client. + +
      • Hamid Maadani (Dextrous Technologies, LLC) added support for +projections and %letter interpolation, and added documentation. + +
      • Wietse Venema adopted and restructured the code and documentation. + +
      + + + + diff --git a/proto/Makefile.in b/proto/Makefile.in index 511bd44..f02ab14 100644 --- a/proto/Makefile.in +++ b/proto/Makefile.in @@ -19,6 +19,7 @@ HTML = ../html/ADDRESS_CLASS_README.html \ ../html/CONTENT_INSPECTION_README.html \ ../html/DATABASE_README.html ../html/DB_README.html \ ../html/DEBUG_README.html \ + ../html/DEPRECATION_README.html \ ../html/DSN_README.html \ ../html/ETRN_README.html ../html/FILTER_README.html \ ../html/FORWARD_SECRECY_README.html \ @@ -30,6 +31,7 @@ HTML = ../html/ADDRESS_CLASS_README.html \ ../html/LMDB_README.html \ ../html/MEMCACHE_README.html \ ../html/MILTER_README.html \ + ../html/MONGODB_README.html \ ../html/MULTI_INSTANCE_README.html \ ../html/MYSQL_README.html ../html/NFS_README.html \ ../html/OVERVIEW.html \ @@ -68,6 +70,7 @@ README = ../README_FILES/ADDRESS_CLASS_README \ ../README_FILES/DATABASE_README ../README_FILES/DB_README \ ../README_FILES/DEBUG_README \ ../README_FILES/DSN_README \ + ../README_FILES/DEPRECATION_README \ ../README_FILES/ETRN_README ../README_FILES/FILTER_README \ ../README_FILES/FORWARD_SECRECY_README \ ../README_FILES/INSTALL ../README_FILES/IPV6_README \ @@ -78,6 +81,7 @@ README = ../README_FILES/ADDRESS_CLASS_README \ ../README_FILES/LMDB_README \ ../README_FILES/MEMCACHE_README \ ../README_FILES/MILTER_README \ + ../README_FILES/MONGODB_README \ ../README_FILES/MULTI_INSTANCE_README \ ../README_FILES/MYSQL_README ../README_FILES/NFS_README \ ../README_FILES/OVERVIEW \ @@ -198,6 +202,9 @@ clobber: ../html/DEBUG_README.html: DEBUG_README.html $(DETAB) $? | $(POSTLINK) >$@ +../html/DEPRECATION_README.html: DEPRECATION_README.html + $(DETAB) $? | $(POSTLINK) >$@ + ../html/DSN_README.html: DSN_README.html $(DETAB) $? | $(POSTLINK) >$@ @@ -240,6 +247,9 @@ clobber: ../html/MILTER_README.html: MILTER_README.html $(DETAB) $? | $(POSTLINK) >$@ +../html/MONGODB_README.html: MONGODB_README.html + $(DETAB) $? | $(POSTLINK) >$@ + ../html/MULTI_INSTANCE_README.html: MULTI_INSTANCE_README.html $(DETAB) $? | $(POSTLINK) >$@ @@ -381,6 +391,9 @@ clobber: ../README_FILES/DSN_README: DSN_README.html $(DETAB) $? | $(HT2READ) >$@ +../README_FILES/DEPRECATION_README: DEPRECATION_README.html + $(DETAB) $? | $(HT2READ) >$@ + ../README_FILES/ETRN_README: ETRN_README.html $(DETAB) $? | $(HT2READ) >$@ @@ -420,6 +433,9 @@ clobber: ../README_FILES/MILTER_README: MILTER_README.html $(DETAB) $? | $(HT2READ) >$@ +../README_FILES/MONGODB_README: MONGODB_README.html + $(DETAB) $? | $(HT2READ) >$@ + ../README_FILES/MULTI_INSTANCE_README: MULTI_INSTANCE_README.html $(DETAB) $? | $(HT2READ) >$@ diff --git a/proto/POSTSCREEN_README.html b/proto/POSTSCREEN_README.html index eb9c9f5..afd5cd3 100644 --- a/proto/POSTSCREEN_README.html +++ b/proto/POSTSCREEN_README.html @@ -120,7 +120,7 @@ of time to deliver spam before their IP address becomes denylisted. To speed up spam deliveries, zombies make compromises in their SMTP protocol implementation. For example, they speak before their turn, or they ignore responses from SMTP servers and continue sending -mail even when the server tells them to go away.

      +commands even when the server tells them to go away.

      postscreen(8) uses a variety of measurements to recognize zombies. First, postscreen(8) determines if the remote SMTP client @@ -159,7 +159,7 @@ overhead for legitimate clients.

      Quick tests before everything else

      -

      Before engaging in SMTP-level tests. postscreen(8) queries a +

      Before engaging in SMTP-level tests, postscreen(8) queries a number of local deny and allowlists. These tests speed up the handling of known clients.

      diff --git a/proto/TLS_README.html b/proto/TLS_README.html index a390566..d6fe51b 100644 --- a/proto/TLS_README.html +++ b/proto/TLS_README.html @@ -2266,82 +2266,124 @@ describe the corresponding table syntax:

      additional attributes are supported at this level.
      may
      Opportunistic TLS. -The optional "ciphers", "exclude" and "protocols" attributes -(available for opportunistic TLS with Postfix ≥ 2.6) override the -"smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols" -configuration parameters. At this level and higher, the optional -"servername" attribute (available with Postfix ≥ 3.4) overrides the -global "smtp_tls_servername" parameter, enabling per-destination -configuration of the SNI extension sent to the remote SMTP server.
      +The optional "ciphers", "exclude", and "protocols" attributes (available +for opportunistic TLS with Postfix ≥ 2.6) and "connection_reuse" +attribute (Postfix ≥ 3.4) override the "smtp_tls_ciphers", +"smtp_tls_exclude_ciphers", "smtp_tls_protocols", and +"smtp_tls_connection_reuse" configuration parameters. At this level and +higher, the optional "servername" attribute (available with Postfix ≥ +3.4) overrides the global "smtp_tls_servername" parameter, enabling +per-destination configuration of the SNI extension sent to the remote +SMTP server. The optional "enable_rpk" attribute (Postfix ≥ 3.9) +overrides the main.cf smtp_tls_enable_rpk parameter. When opportunistic +TLS handshakes fail, Postfix retries the connection with TLS disabled. +This allows mail delivery to sites with non-interoperable TLS +implementations.
      encrypt
      Mandatory encryption. -Mail is delivered only if the remote SMTP server offers STARTTLS -and the TLS handshake succeeds. At this level and higher, the optional +Mail is delivered only if the remote SMTP server offers STARTTLS and the +TLS handshake succeeds. At this level and higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols -parameter, the optional "ciphers" attribute overrides the -main.cf smtp_tls_mandatory_ciphers parameter, and the optional -"exclude" attribute (Postfix ≥ 2.6) overrides the main.cf -smtp_tls_mandatory_exclude_ciphers parameter.
      +parameter, the optional "ciphers" attribute overrides the main.cf +smtp_tls_mandatory_ciphers parameter, the optional "exclude" attribute +(Postfix ≥ 2.6) overrides the main.cf +smtp_tls_mandatory_exclude_ciphers parameter, and the optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute +(Postfix ≥ 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. +
      dane
      Opportunistic DANE TLS. The TLS policy for the destination is obtained via TLSA records in -DNSSEC. If no TLSA records are found, the effective security level -used is may. If TLSA records are -found, but none are usable, the effective security level is encrypt. When usable TLSA records -are obtained for the remote SMTP server, SSLv2+3 are automatically -disabled (see smtp_tls_mandatory_protocols), and the server certificate -must match the TLSA records. RFC 7672 (DANE) TLS authentication -and DNSSEC support is available with Postfix 2.11 and later.
      +DNSSEC. If no TLSA records are found, the effective security level used +is may. If TLSA records are found, but +none are usable, the effective security level is encrypt. When usable TLSA records are +obtained for the remote SMTP server, the server certificate must match +the TLSA records (and the SNI name is unconditionally set to the TLSA +base domain). RFC 7672 (DANE) TLS authentication and DNSSEC +support is available with Postfix 2.11 and later. The optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. When the effective security level +used is may, the optional "ciphers", +"exclude", and "protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_ciphers", "smtp_tls_exclude_ciphers", and "smtp_tls_protocols" +configuration parameters. When the effective security level used is encrypt, the optional "ciphers", +"exclude", and "protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and +"smtp_tls_mandatory_protocols" configuration parameters.
      dane-only
      Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA records in -DNSSEC. If no TLSA records are found, or none are usable, no -connection is made to the server. When usable TLSA records are -obtained for the remote SMTP server, SSLv2+3 are automatically disabled -(see smtp_tls_mandatory_protocols), and the server certificate must -match the TLSA records. RFC 7672 (DANE) TLS authentication and -DNSSEC support is available with Postfix 2.11 and later.
      +DNSSEC. If no TLSA records are found, or none are usable, no connection +is made to the server. When usable TLSA records are obtained for the +remote SMTP server, the server certificate must match the TLSA records. +RFC 7672 (DANE) TLS authentication and DNSSEC support is available with +Postfix 2.11 and later. The optional "ciphers", "exclude", and +"protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and +"smtp_tls_mandatory_protocols" configuration parameters. The optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter.
      fingerprint
      Certificate -fingerprint verification. Available with Postfix 2.5 and -later. At this security level, there are no trusted Certification -Authorities. The certificate trust chain, expiration date, ... are -not checked. Instead, the optional match attribute, or else -the main.cf smtp_tls_fingerprint_cert_match parameter, lists -the server certificate fingerprints or public key fingerprints -(Postfix 2.9 and later). The -digest algorithm used to calculate fingerprints is selected by the -smtp_tls_fingerprint_digest parameter. Multiple fingerprints can -be combined with a "|" delimiter in a single match attribute, or multiple -match attributes can be employed. The ":" character is not used as a -delimiter as it occurs between each pair of fingerprint (hexadecimal) -digits.
      +fingerprint verification. Available with Postfix 2.5 and later. At +this security level, there are no trusted Certification Authorities. The +certificate trust chain, expiration date, ... are not checked. Instead, +the optional "match" attribute, or else the main.cf +smtp_tls_fingerprint_cert_match parameter, lists the certificate +fingerprints or the public key fingerprints (Postfix 2.9 and later) of +acceptable server certificates. The digest algorithm used to calculate +the fingerprint is selected by the smtp_tls_fingerprint_digest +parameter. Multiple fingerprints can be combined with a "|" delimiter in +a single match attribute, or multiple match attributes can be employed. +The ":" character is not used as a delimiter as it occurs between each +pair of fingerprint (hexadecimal) digits. The optional "ciphers", +"exclude", and "protocols" attributes (Postfix ≥ 2.6) override the +"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and +"smtp_tls_mandatory_protocols" configuration parameters. The optional +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. The optional "enable_rpk" +attribute (Postfix ≥ 3.9) overrides the main.cf smtp_tls_enable_rpk +parameter.
      verify
      Mandatory -server certificate verification. Mail is delivered only if the -TLS handshake succeeds, if the remote SMTP server certificate can -be validated (not expired or revoked, and signed by a trusted -Certification Authority), and if the server certificate name matches -the optional "match" attribute (or the main.cf smtp_tls_verify_cert_match -parameter value when no optional "match" attribute is specified). -With Postfix ≥ 2.11 the "tafile" attribute optionally modifies -trust chain verification in the same manner as the -"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute -may be specified multiple times to load multiple trust-anchor -files.
      +server certificate verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups are presumed to be +secure enough, and the name verified in the server certificate is +potentially obtained via unauthenticated DNS MX lookups. The server +certificate name must match either the optional "match" attribute, or +else the main.cf smtp_tls_verify_cert_match parameter value. With +Postfix ≥ 2.11 the "tafile" attribute optionally modifies trust chain +verification in the same manner as the "smtp_tls_trust_anchor_file" +parameter. The "tafile" attribute may be specified multiple times to +load multiple trust-anchor files. The optional "connection_reuse" +attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter.
      secure
      Secure certificate -verification. Mail is delivered only if the TLS handshake succeeds, -and DNS forgery resistant remote SMTP certificate verification succeeds -(not expired or revoked, and signed by a trusted Certification Authority), -and if the server certificate name matches the optional "match" attribute -(or the main.cf smtp_tls_secure_cert_match parameter value when no optional -"match" attribute is specified). With Postfix ≥ 2.11 the "tafile" -attribute optionally modifies trust chain verification in the same manner -as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute -may be specified multiple times to load multiple trust-anchor -files.
      +verification. +Mail is delivered only if the TLS handshake succeeds, the remote SMTP +server certificate chain can be validated, and a DNS name in the +certificate matches the specified match criteria. At this security +level, DNS MX lookups, though potentially used to determine the +candidate next-hop gateway IP addresses, are not presumed to be +secure enough for TLS peername verification. Instead, the default name +verified in the server certificate is obtained directly from the +next-hop, or is explicitly specified via the optional "match" attribute +which overrides the main.cf smtp_tls_secure_cert_match parameter. The +optional "ciphers", "exclude", and "protocols" attributes (Postfix ≥ +2.6) override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix ≥ 2.11 the "tafile" attribute +optionally modifies trust chain verification in the same manner as the +"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be +specified multiple times to load multiple trust-anchor files. The +optional "connection_reuse" attribute (Postfix ≥ 3.4) overrides the +main.cf smtp_tls_connection_reuse parameter. diff --git a/proto/access b/proto/access index 0fe2a89..a3787a3 100644 --- a/proto/access +++ b/proto/access @@ -52,7 +52,7 @@ # .IP "multi-line text" # A logical line starts with non-whitespace text. A line that # starts with whitespace continues a logical line. -# EMAIL ADDRESS PATTERNS +# EMAIL ADDRESS PATTERNS IN INDEXED TABLES # .ad # .fi # With lookups from indexed files such as DB or DBM, or from networked @@ -85,7 +85,7 @@ # (e.g., \fIuser+foo\fR@\fIdomain\fR), the lookup order becomes: # \fIuser+foo\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR, \fIdomain\fR, # \fIuser+foo\fR@, and \fIuser\fR@. -# HOST NAME/ADDRESS PATTERNS +# HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES # .ad # .fi # With lookups from indexed files such as DB or DBM, or from networked diff --git a/proto/aliases b/proto/aliases index d2d3f19..f48a00b 100644 --- a/proto/aliases +++ b/proto/aliases @@ -7,9 +7,13 @@ # .fi # \fBnewaliases\fR # DESCRIPTION -# The \fBaliases\fR(5) table provides a system-wide mechanism to -# redirect mail for local recipients. The redirections are -# processed by the Postfix \fBlocal\fR(8) delivery agent. +# The optional \fBaliases\fR(5) table (alias_maps) redirects +# mail for local recipients. The redirections are processed +# by the Postfix \fBlocal\fR(8) delivery agent. +# +# This is unlike \fBvirtual\fR(5) aliasing (virtual_alias_maps) +# which applies to all recipients: local(8), virtual, and remote, +# and which is implemented by the \fBcleanup\fR(8) daemon. # # Normally, the \fBaliases\fR(5) table is specified as a text file # that serves as input to the \fBpostalias\fR(1) command. The @@ -149,7 +153,9 @@ # The alias databases for \fBlocal\fR(8) delivery that are updated with # "\fBnewaliases\fR" or with "\fBsendmail -bi\fR". # .IP "\fBalias_maps (see 'postconf -d' output)\fR" -# The alias databases that are used for \fBlocal\fR(8) delivery. +# Optional lookup tables with aliases that apply only to \fBlocal\fR(8) +# recipients; this is unlike virtual_alias_maps that apply to all +# recipients: \fBlocal\fR(8), virtual, and remote. # .IP "\fBallow_mail_to_commands (alias, forward)\fR" # Restrict \fBlocal\fR(8) mail delivery to external commands. # .IP "\fBallow_mail_to_files (alias, forward)\fR" diff --git a/proto/canonical b/proto/canonical index 6364d3e..5ffc8d1 100644 --- a/proto/canonical +++ b/proto/canonical @@ -207,17 +207,14 @@ # .PP # Other parameters of interest: # .IP "\fBinet_interfaces (all)\fR" -# The network interface addresses that this mail system receives -# mail on. +# The local network interface addresses that this mail system +# receives mail on. # .IP "\fBlocal_header_rewrite_clients (permit_inet_interfaces)\fR" -# Rewrite message header addresses in mail from these clients and -# update incomplete addresses with the domain name in $myorigin or -# $mydomain; either don't rewrite message headers from other clients -# at all, or rewrite message headers and update incomplete addresses -# with the domain specified in the remote_header_rewrite_domain -# parameter. +# Rewrite or add message headers in mail from these clients, +# updating incomplete addresses with the domain name in $myorigin or +# $mydomain, and adding missing headers. # .IP "\fBproxy_interfaces (empty)\fR" -# The network interface addresses that this mail system receives mail +# The remote network interface addresses that this mail system receives mail # on by way of a proxy or network address translation unit. # .IP "\fBmasquerade_classes (envelope_sender, header_sender, header_recipient)\fR" # What addresses are subject to address masquerading. @@ -239,9 +236,10 @@ # \fIlistname\fR-request address localparts when the recipient_delimiter # is set to "-". # .IP "\fBremote_header_rewrite_domain (empty)\fR" -# Don't rewrite message headers from remote clients at all when -# this parameter is empty; otherwise, rewrite message headers and -# append the specified domain name to incomplete addresses. +# Rewrite or add message headers in mail from remote clients if +# the remote_header_rewrite_domain parameter value is non-empty, +# updating incomplete addresses with the domain specified in the +# remote_header_rewrite_domain parameter, and adding missing headers. # SEE ALSO # cleanup(8), canonicalize and enqueue mail # postmap(1), Postfix lookup table manager diff --git a/proto/generic b/proto/generic index fdeb1ea..dc0ad41 100644 --- a/proto/generic +++ b/proto/generic @@ -188,10 +188,10 @@ # .PP # Other parameters of interest: # .IP "\fBinet_interfaces (all)\fR" -# The network interface addresses that this mail system receives -# mail on. +# The local network interface addresses that this mail system +# receives mail on. # .IP "\fBproxy_interfaces (empty)\fR" -# The network interface addresses that this mail system receives mail +# The remote network interface addresses that this mail system receives mail # on by way of a proxy or network address translation unit. # .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" # The list of domains that are delivered via the $local_transport diff --git a/proto/header_checks b/proto/header_checks index 1aa6f5a..9a6b55c 100644 --- a/proto/header_checks +++ b/proto/header_checks @@ -418,34 +418,24 @@ # CONFIGURATION PARAMETERS # .ad # .fi -# .IP \fBbody_checks\fR -# Lookup tables with content filter rules for message body lines. -# These filters see one physical line at a time, in chunks of -# at most \fB$line_length_limit\fR bytes. -# .IP \fBbody_checks_size_limit\fP -# The amount of content per message body segment (attachment) that is -# subjected to \fB$body_checks\fR filtering. -# .IP \fBheader_checks\fR -# .IP "\fBmime_header_checks\fR (default: \fB$header_checks\fR)" -# .IP "\fBnested_header_checks\fR (default: \fB$header_checks\fR)" -# Lookup tables with content filter rules for message header lines: -# respectively, these are applied to the initial message headers -# (not including MIME headers), to the MIME headers anywhere in -# the message, and to the initial headers of attached messages. -# .sp -# Note: these filters see one logical message header at a time, even -# when a message header spans multiple lines. Message headers that -# are longer than \fB$header_size_limit\fR characters are truncated. -# .IP \fBdisable_mime_input_processing\fR -# While receiving mail, give no special treatment to MIME related -# message headers; all text after the initial message headers is -# considered to be part of the message body. This means that -# \fBheader_checks\fR is applied to all the initial message headers, -# and that \fBbody_checks\fR is applied to the remainder of the -# message. -# .sp -# Note: when used in this manner, \fBbody_checks\fR will process -# a multi-line message header one line at a time. +# .IP "\fBbody_checks (empty)\fR" +# Optional lookup tables for content inspection as specified in +# the \fBbody_checks\fR(5) manual page. +# .IP "\fBbody_checks_size_limit (51200)\fR" +# How much text in a message body segment (or attachment, if you +# prefer to use that term) is subjected to body_checks inspection. +# .IP "\fBheader_checks (empty)\fR" +# Optional lookup tables for content inspection of primary non-MIME +# message headers, as specified in the \fBheader_checks\fR(5) manual page. +# .IP "\fBmime_header_checks ($header_checks)\fR" +# Optional lookup tables for content inspection of MIME related +# message headers, as described in the \fBheader_checks\fR(5) manual page. +# .IP "\fBnested_header_checks ($header_checks)\fR" +# Optional lookup tables for content inspection of non-MIME message +# headers in attached messages, as described in the \fBheader_checks\fR(5) +# manual page. +# .IP "\fBdisable_mime_input_processing (no)\fR" +# Turn off MIME processing while receiving mail. # EXAMPLES # .ad # .fi diff --git a/proto/master b/proto/master index 28040b6..67477fd 100644 --- a/proto/master +++ b/proto/master @@ -219,10 +219,16 @@ # .IP \fB-v\fR # Increase the verbose logging level. Specify multiple \fB-v\fR # options to make a Postfix daemon process increasingly verbose. -# .IP "Other command-line arguments" +# .IP "\fBCommand-line arguments that start with {\fR" +# With Postfix 3.0 and later specify "{" and "}" around command +# arguments that start with "{". The outer "{" and "}" are +# removed from the input, together with any leading or trailing +# whitespace. +# .IP "\fBOther command-line arguments\fR" # Specify "{" and "}" around command arguments that contain -# whitespace (Postfix 3.0 and later). Whitespace -# after "{" and before "}" is ignored. +# whitespace (Postfix 3.0 and later). The outer "{" and "}" +# are removed from the input, together with any leading or +# trailing whitespace. # SEE ALSO # master(8), process manager # postconf(5), configuration parameters diff --git a/proto/mongodb_table b/proto/mongodb_table new file mode 100644 index 0000000..81dfc8e --- /dev/null +++ b/proto/mongodb_table @@ -0,0 +1,240 @@ +#++ +# NAME +# mongodb_table 5 +# SUMMARY +# Postfix MongoDB client configuration +# SYNOPSIS +# \fBpostmap -q "\fIstring\fB" mongodb:/etc/postfix/\fIfilename\fR +# +# \fBpostmap -q - mongodb:/etc/postfix/\fIfilename\fB <\fIinputfile\fR +# DESCRIPTION +# The Postfix mail system uses optional tables for address +# rewriting or mail routing. These tables are usually in +# \fBdbm\fR or \fBdb\fR format. +# +# Alternatively, lookup tables can be specified as MongoDB +# databases. In order to use MongoDB lookups, define a MongoDB +# source as a lookup table in main.cf, for example: +# .nf +# alias_maps = mongodb:/etc/postfix/mongodb-aliases.cf +# .fi +# +# In this example, the file /etc/postfix/mongodb-aliases.cf +# has the same format as the Postfix main.cf file, and can +# specify the parameters described below. It is also possible +# to have the configuration in main.cf; see "OBSOLETE MAIN.CF +# PARAMETERS" below. +# +# It is strongly recommended to use proxy:mongodb, in order +# to reduce the number of database connections. For example: +# .nf +# alias_maps = proxy:mongodb:/etc/postfix/mongodb-aliases.cf +# .fi +# +# Note: when using proxy:mongodb:/\fIfile\fR, the file must +# be readable by the unprivileged postfix user (specified +# with the Postfix mail_owner configuration parameter). +# MONGODB PARAMETERS +# .ad +# .fi +# .IP "\fBuri\fR" +# The URI of mongo server/cluster that Postfix will try to +# connect to and query from. Please see +# .nf +# https://www.mongodb.com/docs/manual/reference/connection-string/ +# .fi +# +# Example: +# .nf +# uri = mongodb+srv://user:pass@loclhost:27017/mail +# .fi +# .IP "\fBdbname\fR" +# Name of the database to read the information from. +# Example: +# .nf +# dbname = mail +# .fi +# .IP "\fBcollection\fR" +# Name of the collection (table) to read the information from. +# Example: +# .nf +# collection = mailbox +# .fi +# .IP "\fBquery_filter\fR" +# The MongoDB query template used to search the database, +# where \fB%s\fR is a substitute for the email address that +# Postfix is trying to resolve. Please see: +# .nf +# https://www.mongodb.com/docs/manual/tutorial/query-documents/ +# .fi +# +# Example: +# .nf +# query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1} +# .fi +# +# This parameter supports the following '%' expansions: +# .RS +# .IP "\fB%%\fR" +# This is replaced by a literal '%' character. +# .IP "\fB%s\fR" +# This is replaced by the input key. The %s must appear in +# quotes, because all Postfix queries are strings containing +# (parts from) a domain or email address. Postfix makes no +# numerical queries. +# .IP "\fB%u\fR" +# When the input key is an address of the form user@domain, +# \fB%u\fR is replaced by the local part of the address. +# Otherwise, \fB%u\fR is replaced by the entire search string. +# .IP "\fB%d\fR" +# When the input key is an address of the form user@domain, +# \fB%d\fR is replaced by the domain part of the address. +# .IP "\fB%[1-9]\fR" +# The patterns %1, %2, ... %9 are replaced by the corresponding +# most significant component of the input key's domain. If +# the input key is \fIuser@mail.example.com\fR, then %1 is +# \fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR. +# .RE +# .IP +# In the above substitutions, characters will be quoted as +# required by RFC 4627. For example, each double quote or +# backslash character will be escaped with a backslash +# characacter. +# .IP "\fBprojection\fR" +# Advanced MongoDB query projections. Please see: +# .nf +# https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/ +# .fi +# +# .RS +# .IP \(bu +# If \fBprojection\fR is non-empty, then \fBresult_attribute\fR +# must be empty. +# .IP \(bu +# This implementation can extract information only from result +# fields that have type \fBstring\fR (UTF8), \fBinteger\fR +# (int32, int64) and \fBarray\fR. Other result fields will +# be ignored with a warning. Please see: +# .nf +# https://mongoc.org/libbson/current/bson_type_t.html +# .fi +# .IP \(bu +# As with \fBresult_attribute\fR, the top-level _id field +# (type OID) is automatically removed from projection results. +# .RE +# .IP "\fBresult_attribute\fR" +# Comma or whitespace separated list with the names of fields +# to be returned in a lookup result. +# +# .RS +# .IP \(bu +# If \fBresult_attribute\fR is non-empty, then \fBprojection\fR +# must be empty. +# .IP \(bu +# As with \fBprojection\fR, the top-level _id field (type +# OID) is automatically removed from lookup results. +# .RE +# .IP "\fBresult_format (default: \fB%s\fR)\fR" +# Format template applied to the result from \fBprojection\fR +# or \fBresult_attribute\fR. Most commonly used to append (or +# prepend) text to the result. This parameter supports the +# following '%' expansions: +# .RS +# .IP "\fB%%\fR" +# This is replaced by a literal '%' character. +# .IP "\fB%s\fR" +# This is replaced by the value of the result attribute. When +# result is empty it is skipped. +# .IP "\fB%u\fR +# When the result attribute value is an address of the form +# user@domain, \fB%u\fR is replaced by the local part of the +# address. When the result has an empty localpart it is +# skipped. +# .IP "\fB%d\fR" +# When a result attribute value is an address of the form +# user@domain, \fB%d\fR is replaced by the domain part of the +# attribute value. When the result is unqualified it is +# skipped. +# .IP "\fB%[SUD1-9]\fR" +# The upper-case and decimal digit expansions interpolate the +# parts of the input key rather than the result. Their behavior +# is identical to that described with \fBquery_filter\fR, and +# in fact because the input key is known in advance, lookups +# whose key does not contain all the information specified +# in the result template are suppressed and return no results. +# .RE +# .IP +# For example, using "result_format = smtp:[%s]" allows one +# to use a mailHost attribute as the basis of a transport(5) +# table. After applying the result format, multiple values +# are concatenated as comma separated strings. The expansion_limit +# parameter explained below allows one to restrict the number +# of values in the result, which is especially useful for +# maps that should return a single value. +# +# The default value \fB%s\fR specifies that each +# attribute value should be used as is. +# +# NOTE: DO NOT put quotes around the result format! The result +# is not a JSON string. +# .IP "\fBdomain (default: no domain list)\fR" +# This is a list of domain names, paths to files, or "type:table" +# databases. When specified, only fully qualified search keys +# with a *non-empty* localpart and a matching domain are +# eligible for lookup: 'user' lookups, bare domain lookups +# and "@domain" lookups are not performed. This can significantly +# reduce the query load on the backend database. Example: +# .nf +# domain = postfix.org, hash:/etc/postfix/searchdomains +# .fi +# .IP "\fBexpansion_limit (default: 0)\fR" +# A limit on the total number of result elements returned (as +# a comma separated list) by a lookup against the map. A +# setting of zero disables the limit. Lookups fail with a +# temporary error if the limit is exceeded. Setting the limit +# to 1 ensures that lookups do not return multiple values. +# OBSOLETE MAIN.CF PARAMETERS +# .ad +# .fi +# MongoDB parameters can also be defined in main.cf. Specify +# as MongoDB source a name that doesn't begin with a slash +# or a dot. The MongoDB parameters will then be accessible +# as the name you've given the source in its definition, an +# underscore, and the name of the parameter. For example, if +# a map is specified as "mongodb:\fImongodb_source\fR", the +# "uri" parameter would be defined in main.cf as +# "\fImongodb_source\fR_uri". +# +# Note: with this form, passwords are written in main.cf, +# which is normally world-readable, and '$' in a mongodb +# parameter setting needs to be written as '$$'. +# SEE ALSO +# postmap(1), Postfix lookup table maintenance +# postconf(5), configuration parameters +# README FILES +# .ad +# .fi +# Use "\fBpostconf readme_directory\fR" or "\fBpostconf +# html_directory\fR" to locate this information. +# .na +# .nf +# DATABASE_README, Postfix lookup table overview +# MONGODB_README, Postfix MONGODB client guide +# LICENSE +# .ad +# .fi +# The Secure Mailer license must be distributed with this software. +# HISTORY +# MongoDB support was introduced with Postfix version 3.9. +# AUTHOR(S) +# Hamid Maadani (hamid@dexo.tech) +# Dextrous Technologies, LLC +# +# Edited by: +# Wietse Venema +# porcupine.org +# +# Based on prior work by: +# Stephan Ferraro +# Aionda GmbH +#-- diff --git a/proto/mysql_table b/proto/mysql_table index a018e58..31e626f 100644 --- a/proto/mysql_table +++ b/proto/mysql_table @@ -79,6 +79,24 @@ # .nf # dbname = customer_database # .fi +# .IP "\fBcharset (default: utf8mb4)\fR" +# The default MySQL client character set; this also implies +# the collation order. +# +# This parameter is available with Postfix 3.9 and later. +# With earlier Postfix versions, the default was chosen by +# the MySQL implementation (\fButf8mb4\fR as of MySQL 8.0, +# \fBlatin1\fR historically). +# .IP "\fBidle_interval (default: 60)\fR" +# The number of seconds after which an idle database connection +# will be closed. +# +# This feature is available in Postfix 3.9 and later. +# .IP "\fBretry_interval (default: 60)\fR" +# The number of seconds that a database connection will be +# skipped after an error. +# +# This feature is available in Postfix 3.9 and later. # .IP "\fBquery\fR" # The SQL query template used to search the database, where \fB%s\fR # is a substitute for the address Postfix is trying to resolve, diff --git a/proto/pcre_table b/proto/pcre_table index 0f58c2b..e4c6607 100644 --- a/proto/pcre_table +++ b/proto/pcre_table @@ -190,9 +190,14 @@ # # Postfix parses the result as if it is a file in /etc/postfix. # -# Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep -# Postfix from trying to do \fI$name\fR expansion as it -# evaluates a parameter value. +# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +# to keep Postfix from trying to do \fI$name\fR expansion as +# it evaluates a parameter value. +# +# Note: when using \fI$name\fR inside an inlined pattern, use +# \eQ\fI$name\fR\eE to disable metacharacters such as '.' in +# the \fI$name\fR expansion. Otherwise, the pattern may have +# unexpected matches. # EXAMPLE SMTPD ACCESS MAP # # Protect your outgoing majordomo exploders # /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead diff --git a/proto/pgsql_table b/proto/pgsql_table index 0a2897a..b4364fb 100644 --- a/proto/pgsql_table +++ b/proto/pgsql_table @@ -80,10 +80,21 @@ # .nf # encoding = UTF8 # .fi +# # Historically, the database client was hard coded to use # LATIN1 in an attempt to disable multibyte character support. # # This feature is available in Postfix 3.8 and later. +# .IP "\fBidle_interval (default: 60)\fR" +# The number of seconds after which an idle database connection +# will be closed. +# +# This feature is available in Postfix 3.9 and later. +# .IP "\fBretry_interval (default: 60)\fR" +# The number of seconds that a database connection will be +# skipped after an error. +# +# This feature is available in Postfix 3.9 and later. # .IP "\fBquery\fR" # The SQL query template used to search the database, where \fB%s\fR # is a substitute for the address Postfix is trying to resolve, diff --git a/proto/postconf.proto b/proto/postconf.proto index f52f37f..d13719b 100644 --- a/proto/postconf.proto +++ b/proto/postconf.proto @@ -489,8 +489,14 @@ alias_database = hash:/etc/mail/aliases %PARAM alias_maps see "postconf -d" output

      -The alias databases that are used for local(8) delivery. See -aliases(5) for syntax details. +Optional lookup tables with aliases that apply only to local(8) +recipients; this is unlike virtual_alias_maps that apply to all +recipients: local(8), virtual, and remote. +The table format and lookups are documented in aliases(5). For an +overview of Postfix address manipulations see the ADDRESS_REWRITING_README +document.

      + +

      Specify zero or more "type:name" lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. @@ -1315,19 +1321,30 @@ name of the message delivery transport.

      The default mail delivery transport and next-hop destination for -destinations that do not match $mydestination, $inet_interfaces, +the default domain class: recipient domains that do not match +$mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, -or $relay_domains. This information can be overruled with the -sender_dependent_default_transport_maps parameter and with the -transport(5) table.

      +or $relay_domains. This information will not be used when +sender_dependent_default_transport_maps returns a result, and may +be overridden with the transport(5) table.

      -

      -In order of decreasing precedence, the nexthop destination is taken -from $sender_dependent_default_transport_maps, $default_transport, -$sender_dependent_relayhost_maps, $relayhost, or from the recipient -domain. +

      For recipient domains in the default domain class:

      + +

        + +
      • In order of decreasing precedence, the delivery transport +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport.

        +
      • In order of decreasing precedence, the nexthop destination +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain.

        + +
      +

      Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. @@ -1766,7 +1783,7 @@ forward_expansion_filter parameter.

      The address extension delimiter that was found in the recipient address (Postfix 2.11 and later), or the 'first' delimiter specified with the system-wide recipient address extension delimiter (Postfix -3.5.22, 3.5.12, 3.7.8, 3.8.3 and later). Historically, this was +3.5.22, 3.6.12, 3.7.8, 3.8.3 and later). Historically, this was always the system-wide recipient address extension delimiter (Postfix 2.10 and earlier).
      @@ -1999,12 +2016,17 @@ Specify 0 to disable the feature. Valid delays are 0..10. %PARAM inet_interfaces all -

      The local network interface addresses that this mail system receives -mail on. Specify "all" to receive mail on all network -interfaces (default), and "loopback-only" to receive mail -on loopback network interfaces only (Postfix version 2.2 and later). The -parameter also controls delivery of mail to user@[ip.address]. -

      +

      The local network interface addresses that this mail system +receives mail on. Specify "all" to receive mail on all network +interfaces (default), "loopback-only" to receive mail on loopback +network interfaces only (Postfix version 2.2 and later), or zero +or more IPv4 or IPv6 addresses (IPv6 is supported in Postfix version +2.2 and later). The parameter also controls whether Postfix will +accept mail for user@[ip.address], and prevents Postfix +from delivering mail to a host that has equal or larger MX preference. +Specify an empty value if Postfix does not receive mail over the +network, or if all network listeners have an explicit IP address +in master.cf.

      Note 1: you need to stop and start Postfix when this parameter changes. @@ -2013,22 +2035,44 @@ Note 1: you need to stop and start Postfix when this parameter changes.

      Note 2: address information may be enclosed inside [], but this form is not required here.

      -

      When inet_interfaces specifies just one IPv4 and/or IPv6 address -that is not a loopback address, the Postfix SMTP client will use -this address as the IP source address for outbound mail. Support -for IPv6 is available in Postfix version 2.2 and later.

      +

      When smtp_bind_address and/or smtp_bind_address6 are not +specified, the inet_interfaces setting may constrain the source IP +address for an outbound SMTP or LMTP connection as described below. +

      -

      -On a multi-homed firewall with separate Postfix instances listening on the -"inside" and "outside" interfaces, this can prevent each instance from -being able to reach remote SMTP servers on the "other side" of the -firewall. Setting -smtp_bind_address to 0.0.0.0 avoids the potential problem for -IPv4, and setting smtp_bind_address6 to :: solves the problem -for IPv6.

      +

      The following text is specific to SMTP and IPv4. The same +reasoning applies to the IPv6 protocol, and to the Postfix LMTP +client. To disable IPv4 or IPv6 support in the Postfix SMTP and +LMTP client, use inet_protocols.

      + +
        + +
      • When inet_interfaces specifies one IPv4 address, and that +is not a loopback address, the Postfix SMTP client uses that as the +source address for outbound IPv4 connections.

        + +
      • Otherwise, the Postfix SMTP client does not constrain the +source IPv4 address, and connects using a system-chosen source IPv4 +address. This includes the cases where inet_interfaces is empty, +where it specifies all, or where it contains no IPv4 address, +one IPv4 address that is a loopback address, or multiple IPv4 +addresses.

        + +
      + +

      A Postfix SMTP client may fail to reach some remote SMTP servers +when the client source IP address is constrained explicitly with +smtp_bind_address or smtp_bind_address6, or implicitly with +inet_interfaces. This can happen when Postfix runs on a multi-homed +system such as a firewall, the Postfix SMTP source client IP address +is constrained to one specific network interface, and the remote +SMTP server must be reached through a different interface. Setting +smtp_bind_address to 0.0.0.0 avoids the potential problem for IPv4, +and setting smtp_bind_address6 to :: solves the problem for IPv6. +

      -A better solution for multi-homed firewalls is to leave inet_interfaces +A better solution for multi-homed systems is to leave inet_interfaces at the default value and instead use explicit IP addresses in the master.cf SMTP server definitions. This preserves the Postfix SMTP client's @@ -2056,7 +2100,7 @@ inet_interfaces = 127.0.0.1, [::1] (Postfix version 2.2 and later) inet_interfaces = 192.168.1.2, 127.0.0.1 -%PARAM inet_protocols see 'postconf -d output' +%PARAM inet_protocols see 'postconf -d' output

      The Internet protocols Postfix will attempt to use when making or accepting connections. Specify one or more of "ipv4" @@ -2427,8 +2471,8 @@ until a match is found.

      If this parameter is non-empty (the default), then the Postfix SMTP -server will reject mail for unknown local users. -

      +server will reject mail for unknown local users. Other Postfix +interfaces may still accept an "unknown" recipient.

      To turn off local recipient checking in the Postfix SMTP server, @@ -2689,6 +2733,11 @@ and later.

      The domain part of the recipient address.
      +
      ENVID
      + +
      The optional RFC 3461 envelope ID. Available in Postfix version +3.9 and later
      +
      EXTENSION
      The optional address extension.
      @@ -3849,13 +3898,31 @@ This feature is available in Postfix 2.0 and later. %PARAM relayhost

      -The next-hop destination(s) for non-local mail; overrides non-local -domains in recipient addresses. This information is overruled with -relay_transport, sender_dependent_default_transport_maps, -default_transport, sender_dependent_relayhost_maps -and with the transport(5) table. +The next-hop destination(s) for non-local mail; takes precedence +over non-local domains in recipient addresses. This information +will not be used when the sender matches $sender_dependent_relayhost_maps.

      +

      In order of decreasing precedence:

      + +
        + +
      • For recipient domains in the relay domain address class +(domains matching $relay_domains), the nexthop destination is taken +from 1) $transport_maps, 2) $relay_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain.

        + +

      • For recipient domains in the default domain address class +(domains that do not match $mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +or $relay_domains), the nexthop destination is taken from 1) +$transport_maps, 2) $sender_dependent_default_transport_maps or +$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost +or the recipient domain.

        + +
      +

      On an intranet, specify the organizational domain name. If your internal DNS uses no MX records, specify the name of the intranet @@ -3863,11 +3930,12 @@ gateway host instead.

      -In the case of SMTP or LMTP delivery, specify one or more destinations -in the form of a domain name, hostname, hostname:port, [hostname]:port, -[hostaddress] or [hostaddress]:port, separated by comma or whitespace. -The form [hostname] turns off MX lookups. Multiple destinations are -supported in Postfix 3.5 and later. +In the case of SMTP delivery, specify one or more destinations in +the form of a domain name, hostname, hostname:service, [hostname]:service, +[hostaddress] or [hostaddress]:service, separated by comma or whitespace. +The form [hostname] turns off MX or SRV lookups. Multiple destinations +are supported in Postfix 3.5 and later. Each destination is tried +in the specified order.

      @@ -4628,6 +4696,9 @@ If no username:password entry is found, then the Postfix SMTP client will not attempt to authenticate to the remote host.

      +

      Use smtp_sasl_password_result_delimiter to specify an +alternative separator between username and password.

      +

      The Postfix SMTP client opens the lookup table before going to chroot jail, so you can leave the password file in /etc/postfix. @@ -4639,6 +4710,19 @@ whitespace or comma. Tables will be searched in the specified order until a match is found.

      +%PARAM lmtp_sasl_password_result_delimiter : + +

      The LMTP-specific version of the smtp_sasl_password_result_delimiter +configuration parameter. See there for details.

      + +%PARAM smtp_sasl_password_result_delimiter : + +

      The delimiter between username and password in sasl_passwd_maps lookup +results. Specify one non-whitespace character that does not appear in +the username.

      + +

      This feature is available in Postfix ≥ 3.9.

      + %PARAM smtp_sasl_security_options noplaintext, noanonymous

      Postfix SMTP client SASL security options; as of Postfix 2.3 @@ -5219,9 +5303,8 @@ pubkey_fingerprint } }

      check_client_access type:table
      -
      Search the specified access database for the client hostname, -parent domains, client IP address, or networks obtained by stripping -least significant octets. See the access(5) manual page for details.
      +
      Search the specified access database for the client hostname +or IP address. See the access(5) manual page for details.
      check_client_a_access type:table
      @@ -5252,8 +5335,7 @@ available in Postfix 2.7 and later.
      check_reverse_client_hostname_access type:table
      Search the specified access database for the unverified reverse -client hostname, parent domains, client IP address, or networks -obtained by stripping least significant octets. See the access(5) +client hostname or IP address. See the access(5) manual page for details. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from denylists. This feature is available in Postfix 2.6 @@ -5726,8 +5808,8 @@ received with the ETRN command.
      check_etrn_access type:table
      -
      Search the specified access database for the ETRN domain name -or its parent domains. See the access(5) manual page for details. +
      Search the specified access database for the ETRN domain name. +See the access(5) manual page for details.
      @@ -5842,7 +5924,7 @@ received with the HELO or EHLO command.
      check_helo_access type:table
      Search the specified access(5) database for the HELO or EHLO -hostname or parent domains, and execute the corresponding action. +hostname, and execute the corresponding action. Note: specify "smtpd_helo_required = yes" to fully enforce this restriction (without "smtpd_helo_required = yes", a client can simply skip check_helo_access by not sending HELO or EHLO).
      @@ -6137,8 +6219,7 @@ that is received with the RCPT TO command.
      check_recipient_access type:table
      Search the specified access(5) database for the resolved RCPT -TO address, domain, parent domains, or localpart@, and execute the -corresponding action.
      +TO address, and execute the corresponding action.
      check_recipient_a_access type:table
      @@ -6388,7 +6469,7 @@ The same restrictions are available as documented under smtpd_recipient_restrictions.

      -

      This feature is available in Postix 2.10 and later.

      +

      This feature is available in Postfix 2.10 and later.

      %CLASS sasl-auth SASL Authentication @@ -6652,8 +6733,7 @@ received with the MAIL FROM command.
      check_sender_access type:table
      Search the specified access(5) database for the MAIL FROM -address, domain, parent domains, or localpart@, and execute the -corresponding action.
      +address, and execute the corresponding action.
      check_sender_a_access type:table
      @@ -6967,7 +7047,14 @@ while accessing the Postfix main.cf configuration file.

      Optional lookup tables with mappings from recipient address to (message delivery transport, next-hop destination). See transport(5) -for details. +for syntax details. +

      + +

      This information may override the message delivery transport +and/or next-hop destination that are specified with $local_transport, +$virtual_transport, $relay_transport, $default_transport, +$sender_dependent_relayhost_maps, $relayhost, +$sender_dependent_default_transport_maps, or the recipient domain.

      @@ -7224,8 +7311,10 @@ This feature is available in Postfix 2.1 and later. %PARAM virtual_alias_maps $virtual_maps

      -Optional lookup tables that alias specific mail addresses or domains -to other local or remote addresses. The table format and lookups +Optional lookup tables with aliases that apply to all recipients: +local(8), virtual, and remote; this is unlike alias_maps that apply +only to local(8) recipients. +The table format and lookups are documented in virtual(5). For an overview of Postfix address manipulations see the ADDRESS_REWRITING_README document.

      @@ -8457,13 +8546,24 @@ configure or operate a specific Postfix subsystem or feature.

      The default mail delivery transport and next-hop destination for -remote delivery to domains listed with $relay_domains. In order of -decreasing precedence, the nexthop destination is taken from -$relay_transport, $sender_dependent_relayhost_maps, $relayhost, or -from the recipient domain. This information can be overruled with -the transport(5) table. +the relay domain address class: recipient domains that match +$relay_domains.

      + +

      For recipient domains in the relay domain address class:

      + +
        + +
      • In order of decreasing precedence, the message delivery +transport is taken from 1) $transport_maps, 2) $relay_transport.

        +
      • In order of decreasing precedence, the nexthop destination +is taken from 1) $transport_maps, 2) $relay_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain.

        + +
      +

      Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. @@ -9698,7 +9798,9 @@ if client certificate verification is not required. With Postfix 2.8 and earlier, log the summary message, peer certificate summary information and unconditionally log trust-chain verification errors. -

      2 Also log levels during TLS negotiation.
      +
      2 Also enable verbose logging in the Postfix TLS +library, log session cache operations, and enable OpenSSL logging +of the progress of the SSL handshake.
      3 Also log hexadecimal and ASCII dump of TLS negotiation process.
      @@ -9733,6 +9835,9 @@ but do not require that clients use TLS encryption.

      STARTTLS due to insufficient privileges to access the server private key. This is intended behavior.

      +

      This feature is deprecated as of Postfix 3.9. Specify +smtpd_tls_security_level instead.

      +

      This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead.

      @@ -9749,6 +9854,9 @@ server. This option is therefore off by default.

      STARTTLS due to insufficient privileges to access the server private key. This is intended behavior.

      +

      This feature is deprecated as of Postfix 3.9. Specify +smtpd_tls_security_level instead.

      +

      This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead.

      @@ -10179,7 +10287,9 @@ verification errors if server certificate verification is not required. With Postfix 2.8 and earlier, log the summary message and unconditionally log trust-chain verification errors. -
      2 Also log levels during TLS negotiation.
      +
      2 Also enable verbose logging in the Postfix TLS +library, log session cache operations, and enable OpenSSL logging +of the progress of the SSL handshake.
      3 Also log the hexadecimal and ASCII dump of the TLS negotiation process.
      @@ -10330,11 +10440,13 @@ lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername settings.
      MAY
      Try to use TLS if the server announces support, -otherwise use an unencrypted connection. This has less precedence +otherwise use an unencrypted connection; after a failed TLS handshake +or TLS session, fall back to plaintext if the message has spent +minimal_backoff_time in the mail queue. This level has less precedence than a more specific result (including NONE) from the alternate host or next-hop lookup key, and has less precedence than the more specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername -= yes".
      += yes".
      MUST_NOPEERMATCH
      Require TLS encryption, but do not require that the remote SMTP server hostname matches the information @@ -10703,9 +10815,28 @@ is placed into the Postfix configuration directory.

      setting. The tables are searched by the envelope sender address and @domain. A lookup result of DUNNO terminates the search without overriding the global relayhost parameter setting (Postfix 2.6 and -later). This information is overruled with relay_transport, -sender_dependent_default_transport_maps, default_transport and with -the transport(5) table.

      +later).

      + +

      In order of decreasing precedence:

      + +
        + +
      • For recipient domains in the relay domain address class +(domains matching $relay_domains), the nexthop destination is taken +from 1) $transport_maps, 2) $relay_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain.

        + +
      • For recipient domains in the default domain address class +(domains that do not match mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +$relay_domains), the nexthop destination is taken from 1) +$transport_maps, 2) $sender_dependent_default_transport_maps or +$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost +or the recipient domain.

        + +
      +

      Specify zero or more "type:name" lookup tables, separated by @@ -10868,6 +10999,9 @@ configuration parameter. See there for details.

      The LMTP-specific version of the smtp_tls_per_site configuration parameter. See there for details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_policy_maps instead.

      +

      This feature is available in Postfix 2.3 and later.

      %PARAM lmtp_generic_maps @@ -10973,6 +11107,9 @@ configuration parameter. See there for details.

      The LMTP-specific version of the smtp_use_tls configuration parameter. See there for details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_security_level instead.

      +

      This feature is available in Postfix 2.3 and later.

      %PARAM lmtp_enforce_tls no @@ -10980,6 +11117,9 @@ parameter. See there for details.

      The LMTP-specific version of the smtp_enforce_tls configuration parameter. See there for details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +lmtp_tls_security_level instead.

      +

      This feature is available in Postfix 2.3 and later.

      %PARAM lmtp_tls_security_level @@ -11350,28 +11490,35 @@ security are:

      Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces interoperability. The optional "ciphers", "exclude", and "protocols" -attributes (available for opportunistic TLS with Postfix ≥ 2.6) -and "connection_reuse" attribute (Postfix ≥ 3.4) override the +attributes (available for opportunistic TLS with Postfix ≥ 2.6) and +"connection_reuse" attribute (Postfix ≥ 3.4) override the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols", -and -"smtp_tls_connection_reuse" configuration parameters. In the policy table, -multiple ciphers, protocols or excluded ciphers must be separated by colons, -as attribute values may not contain whitespace or commas. When opportunistic -TLS handshakes fail, Postfix retries the connection with TLS disabled. -This allows mail delivery to sites with non-interoperable TLS -implementations.
      +and "smtp_tls_connection_reuse" configuration parameters. In the policy +table, multiple ciphers, protocols or excluded ciphers must be separated +by colons, as attribute values may not contain whitespace or commas. At +this level and higher, the optional "servername" attribute (available +with Postfix ≥ 3.4) overrides the global "smtp_tls_servername" +parameter, enabling per-destination configuration of the SNI extension +sent to the remote SMTP server. The optional "enable_rpk" attribute +(Postfix ≥ 3.9) overrides the main.cf smtp_tls_enable_rpk parameter. +When opportunistic TLS handshakes fail, Postfix retries the connection +with TLS disabled. This allows mail delivery to sites with +non-interoperable TLS implementations.
      encrypt
      -
      Mandatory TLS encryption. At this level -and higher, the optional "protocols" attribute overrides the main.cf +
      Mandatory TLS encryption. Mail is delivered only if the remote SMTP +server offers STARTTLS and the TLS handshake succeeds. At this level and +higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute -overrides the main.cf smtp_tls_mandatory_ciphers parameter, the -optional "exclude" attribute (Postfix ≥ 2.6) overrides the main.cf +overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional +"exclude" attribute (Postfix ≥ 2.6) overrides the main.cf smtp_tls_mandatory_exclude_ciphers parameter, and the optional -"connection_reuse" attribute (Postfix ≥ 3.4) overrides the -main.cf smtp_tls_connection_reuse parameter. In the policy table, -multiple ciphers, protocols or excluded ciphers must be separated by colons, -as attribute values may not contain whitespace or commas.
      +"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf +smtp_tls_connection_reuse parameter. In the policy table, multiple +ciphers, protocols or excluded ciphers must be separated by colons, as +attribute values may not contain whitespace or commas. The optional +"enable_rpk" attribute (Postfix ≥ 3.9) overrides the main.cf +smtp_tls_enable_rpk parameter.
      dane
      Opportunistic DANE TLS. The TLS policy for the destination is @@ -11416,10 +11563,10 @@ configuration parameters. The optional "connection_reuse" attribute verification. Available with Postfix 2.5 and later. At this security level, there are no trusted Certification Authorities. The certificate trust chain, expiration date, ... are not checked. Instead, -the optional "match" attribute, or else the main.cf +the optional policy table "match" attribute, or else the main.cf smtp_tls_fingerprint_cert_match parameter, lists the certificate -fingerprints or the public key fingerprint (Postfix 2.9 and later) -of the valid server certificate. The digest +fingerprints or the public key fingerprints (Postfix 2.9 and later) +of acceptable server certificates. The digest algorithm used to calculate the fingerprint is selected by the smtp_tls_fingerprint_digest parameter. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple @@ -11430,45 +11577,58 @@ digits. The optional "ciphers", "exclude", and "protocols" attributes "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" configuration parameters. The optional "connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf smtp_tls_connection_reuse -parameter.
      +parameter. The optional "enable_rpk" attribute (Postfix ≥ 3.9) +overrides the main.cf smtp_tls_enable_rpk parameter.
      verify
      -
      Mandatory TLS verification. At this security -level, DNS MX lookups are trusted to be secure enough, and the name -verified in the server certificate is usually obtained indirectly via -unauthenticated DNS MX lookups. The optional "match" attribute overrides -the main.cf smtp_tls_verify_cert_match parameter. In the policy table, -multiple match patterns and strategies must be separated by colons. -In practice explicit control over matching is more common with the -"secure" policy, described below. The optional "ciphers", "exclude", -and "protocols" attributes (Postfix ≥ 2.6) override the -"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and -"smtp_tls_mandatory_protocols" configuration parameters. The optional -"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf -smtp_tls_connection_reuse parameter.
      +
      Mandatory TLS verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups are presumed to be +secure enough, and the name verified in the server certificate is +potentially obtained via unauthenticated DNS MX lookups. The optional +"match" attribute overrides the main.cf smtp_tls_verify_cert_match +parameter. In the policy table, multiple match patterns and strategies +must be separated by colons. In practice explicit control over matching +is more common with the "secure" policy, described below. The optional +"ciphers", "exclude", and "protocols" attributes (Postfix ≥ 2.6) +override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix ≥ 2.11 the optional "tafile" +policy table attribute modifies trust chain verification in the same +manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile" +attribute may be specified multiple times to load multiple trust-anchor +files. The optional "connection_reuse" attribute (Postfix ≥ 3.4) +overrides the main.cf smtp_tls_connection_reuse parameter.
      secure
      -
      Secure-channel TLS. At this security level, DNS -MX lookups, though potentially used to determine the candidate next-hop -gateway IP addresses, are not trusted to be secure enough for TLS -peername verification. Instead, the default name verified in the server -certificate is obtained directly from the next-hop, or is explicitly -specified via the optional "match" attribute which overrides the -main.cf smtp_tls_secure_cert_match parameter. In the policy table, -multiple match patterns and strategies must be separated by colons. -The match attribute is most useful when multiple domains are supported by -a common server: the policy entries for additional domains specify matching -rules for the primary domain certificate. While transport table overrides -that route the secondary domains to the primary nexthop also allow secure -verification, they risk delivery to the wrong destination when domains -change hands or are re-assigned to new gateways. With the "match" -attribute approach, routing is not perturbed, and mail is deferred if -verification of a new MX host fails. The optional "ciphers", "exclude", -and "protocols" attributes (Postfix ≥ 2.6) override the -"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and -"smtp_tls_mandatory_protocols" configuration parameters. The optional -"connection_reuse" attribute (Postfix ≥ 3.4) overrides the main.cf -smtp_tls_connection_reuse parameter.
      +
      Secure certificate verification. Mail is delivered only if the TLS +handshake succeeds, the remote SMTP server certificate chain can be +validated, and a DNS name in the certificate matches the specified match +criteria. At this security level, DNS MX lookups, though potentially +used to determine the candidate next-hop gateway IP addresses, are +not presumed to be secure enough for TLS peername verification. +Instead, the default name verified in the server certificate is obtained +directly from the next-hop, or is explicitly specified via the optional +"match" attribute which overrides the main.cf smtp_tls_secure_cert_match +parameter. In the policy table, multiple match patterns and strategies +must be separated by colons. The match attribute is most useful when +multiple domains are supported by a common server: the policy entries +for additional domains specify matching rules for the primary domain +certificate. While transport table overrides that route the secondary +domains to the primary nexthop also allow secure verification, they risk +delivery to the wrong destination when domains change hands or are +re-assigned to new gateways. With the "match" attribute approach, +routing is not perturbed, and mail is deferred if verification of a new +MX host fails. The optional "ciphers", "exclude", and "protocols" +attributes (Postfix ≥ 2.6) override the "smtp_tls_mandatory_ciphers", +"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols" +configuration parameters. With Postfix ≥ 2.11 the "tafile" attribute +optionally modifies trust chain verification in the same manner as the +"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be +specified multiple times to load multiple trust-anchor files. The +optional "connection_reuse" attribute (Postfix ≥ 3.4) overrides the +main.cf smtp_tls_connection_reuse parameter.
      @@ -11724,7 +11884,7 @@ configuration parameter. See there for details.

      This feature is available in Postfix 2.3 and later.

      -%PARAM lmtp_tls_mandatory_protocols see postconf -d output +%PARAM lmtp_tls_mandatory_protocols see 'postconf -d' output

      The LMTP-specific version of the smtp_tls_mandatory_protocols configuration parameter. See there for details.

      @@ -11831,7 +11991,9 @@ destinations via smtp_tls_policy_maps.
      may
      Opportunistic TLS. Use TLS if this is supported by the remote -SMTP server, otherwise use plaintext. Since +SMTP server, otherwise use plaintext; after a failed TLS handshake +or TLS session, fall back to plaintext if the message has spent +minimal_backoff_time in the mail queue. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces interoperability. The "smtp_tls_ciphers" and "smtp_tls_protocols" (Postfix ≥ 2.6) @@ -12902,7 +13064,7 @@ the hostname and IP address. The logging format is "host[address]:port".

      This feature is available in Postfix 2.5 and later.

      -%PARAM smtp_tls_protocols see postconf -d output +%PARAM smtp_tls_protocols see 'postconf -d' output

      TLS protocols that the Postfix SMTP client will use with opportunistic TLS encryption. In main.cf the values are separated by @@ -12982,7 +13144,7 @@ smtp_tls_protocols = !SSLv2, !SSLv3

      This feature is available in Postfix 2.6 and later.

      -%PARAM smtpd_tls_protocols see postconf -d output +%PARAM smtpd_tls_protocols see 'postconf -d' output

      TLS protocols accepted by the Postfix SMTP server with opportunistic TLS encryption. If the list is empty, the server supports all available @@ -13048,7 +13210,7 @@ smtpd_tls_protocols = !SSLv2, !SSLv3

      This feature is available in Postfix 2.6 and later.

      -%PARAM lmtp_tls_protocols see postconf -d output +%PARAM lmtp_tls_protocols see 'postconf -d' output

      The LMTP-specific version of the smtp_tls_protocols configuration parameter. See there for details.

      @@ -14353,9 +14515,9 @@ receive a 421 response.

      %PARAM postscreen_greet_ttl 1d -

      The amount of time that postscreen(8) will use the result from -a successful PREGREET test. During this time, the client IP address -is excluded from this test. The default is relatively short, because +

      The amount of time that postscreen(8) remembers that a client +IP address passed a PREGREET test, before it is required to pass +that test again. The default is relatively short, because a good client can immediately talk to a real Postfix SMTP server.

      Specify a non-zero time value (an integral value plus an optional @@ -14813,18 +14975,38 @@ address and @domain. A lookup result of DUNNO terminates the search without overriding the global default_transport parameter setting. This information is overruled with the transport(5) table.

      -

      -Specify zero or more "type:name" lookup tables, separated by -whitespace or comma. Tables will be searched in the specified order -until a match is found. +

      This setting affects only the default domain address class +(recipient domains that do not match $mydestination, $inet_interfaces, +$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, +or $relay_domains):

      + +
        + +
      • In order of decreasing precedence, the delivery transport +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport.

        +
      • In order of decreasing precedence, the nexthop destination +is taken from 1) $transport_maps, 2) +$sender_dependent_default_transport_maps or $default_transport, 3) +$sender_dependent_relayhost_maps or $relayhost or the recipient +domain.

        + +
      +

      Note: this overrides default_transport, not transport_maps, and therefore the expected syntax is that of default_transport, not the syntax of transport_maps. Specifically, this does not support the transport_maps syntax for null transport, null nexthop, or null email addresses.

      +

      +Specify zero or more "type:name" lookup tables, separated by +whitespace or comma. Tables will be searched in the specified order +until a match is found. +

      +

      For safety reasons, this feature does not allow $number substitutions in regular expression maps.

      @@ -14865,13 +15047,38 @@ IPv6 connectivity:

      • The setting "smtp_address_preference = ipv6" is unsafe. -It can fail to deliver mail when there is an outage that affects -IPv6, while the destination is still reachable over IPv4.

        +All deliveries will suffer delays during an IPv6 outage, even +while the destination is still reachable over IPv4. Mail may be +stuck in the queue with Postfix versions < 3.3 that do not +implement "smtp_balance_inet_protocols". For similar reasons, the +setting "smtp_address_preference = ipv4" is also unsafe.

      • The setting "smtp_address_preference = any" is safe. With -this, mail will eventually be delivered even if there is an outage +this, and "smtp_balance_inet_protocols = yes" (the default), only +half of deliveries will suffer delays if there is an outage that affects IPv6 or IPv4, as long as it does not affect both.

        +
      • The setting "smtp_address_preference = ipv4" is not a +solution for remote servers that flag email received over IPv6 as +more 'spammy' (the client IPv6 address has a bad or missing PTR or +AAAA record, bad network neighbors, etc.). Instead, configure Postfix +to receive mail over both IPv4 and IPv6, and to deliver mail over +only IPv4.

        + +
        +
        +/etc/postfix/main.cf:
        +    inet_protocols = all
        +
        +
        + +
        +
        +/etc/postfix/master.cf
        +    smtp ...other fields... smtp -o inet_protocols=ipv4
        +
        +
        +

      This feature is available in Postfix 2.8 and later.

      @@ -14938,9 +15145,10 @@ defined with the postscreen_dnsbl_sites parameter.

      Specify a negative value to enable this feature. When a client passes the postscreen_dnsbl_allowlist_threshold without having failed other tests, all pending or disabled tests are flagged as -completed with a time-to-live value equal to postscreen_dnsbl_ttl. -When a test was already completed, its time-to-live value is updated -if it was less than postscreen_dnsbl_ttl.

      +completed with an expiration time based on the DNS reply TTL. +When a test was already completed, its expiration time is updated +if it was less than the value based on the DNS reply TTL. See +also postscreen_dnsbl_max_ttl and postscreen_dnsbl_min_ttl.

      This feature is available in Postfix 3.6 and later.

      @@ -14966,9 +15174,9 @@ built-in SMTP protocol engine.

      %PARAM postscreen_dnsbl_ttl 1h -

      The amount of time that postscreen(8) will use the result from -a successful DNS-based reputation test before a client -IP address is required to pass that test again.

      +

      The amount of time that postscreen(8) remembers that a client +IP address passed a DNS-based reputation test, before it is required +to pass that test again.

      Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s @@ -14980,9 +15188,9 @@ replaced by postscreen_dnsbl_max_ttl in Postfix 3.1.

      %PARAM postscreen_dnsbl_min_ttl 60s -

      The minimum amount of time that postscreen(8) will use the -result from a successful DNS-based reputation test before a -client IP address is required to pass that test again. If the DNS +

      The minimum amount of time that postscreen(8) remembers that a +client IP address passed a DNS-based reputation test, before it +is required to pass that test again. If the DNS reply specifies a larger TTL value, that value will be used unless it would be larger than postscreen_dnsbl_max_ttl.

      @@ -14995,9 +15203,9 @@ The default time unit is s (seconds).

      %PARAM postscreen_dnsbl_max_ttl ${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h -

      The maximum amount of time that postscreen(8) will use the -result from a successful DNS-based reputation test before a -client IP address is required to pass that test again. If the DNS +

      The maximum amount of time that postscreen(8) remembers that a +client IP address passed a DNS-based reputation test, before it is +required to pass that test again. If the DNS reply specifies a shorter TTL value, that value will be used unless it would be smaller than postscreen_dnsbl_min_ttl.

      @@ -15043,9 +15251,9 @@ this test the next time the client connects.
      %PARAM postscreen_pipelining_ttl 30d -

      The amount of time that postscreen(8) will use the result from -a successful "pipelining" SMTP protocol test. During this time, the -client IP address is excluded from this test. The default is +

      The amount of time that postscreen(8) remembers that a client +IP address passed a "pipelining" SMTP protocol test, before it is +required to pass that test again. The default is long because a good client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server.

      @@ -15140,9 +15348,9 @@ feature. %PARAM postscreen_non_smtp_command_ttl 30d -

      The amount of time that postscreen(8) will use the result from -a successful "non_smtp_command" SMTP protocol test. During this -time, the client IP address is excluded from this test. The default +

      The amount of time that postscreen(8) remembers that a client +IP address passed a "non_smtp_command" SMTP protocol test, before +it is required to pass that test again. The default is long because a client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server.

      @@ -15233,9 +15441,9 @@ this test the next time the client connects. %PARAM postscreen_bare_newline_ttl 30d -

      The amount of time that postscreen(8) will use the result from -a successful "bare newline" SMTP protocol test. During this -time, the client IP address is excluded from this test. The default +

      The amount of time that postscreen(8) remembers that a client +IP address passed a "bare newline" SMTP protocol test, before it +address is required to pass that test again. The default is long because a remote SMTP client must disconnect after it passes the test, before it can talk to a real Postfix SMTP server.

      @@ -15542,6 +15750,9 @@ for details.

      require that clients use TLS encryption. See smtpd_enforce_tls for further details. Use tlsproxy_tls_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_tls_security_level instead.

      +

      This feature is available in Postfix 2.8 and later.

      %PARAM tlsproxy_tls_CAfile $smtpd_tls_CAfile @@ -15616,6 +15827,8 @@ smtpd_tls_dcert_file for further details.

      should use with non-export EDH ciphers. See smtpd_tls_dh1024_param_file for further details.

      +

      This feature is deprecated as of Postfix 3.9. Do not specify.

      +

      This feature is available in Postfix 2.8 and later.

      %PARAM tlsproxy_tls_dh512_param_file $smtpd_tls_dh512_param_file @@ -15668,6 +15881,8 @@ the "tlsproxy_tls_chain_files" parameter.

      elliptic-curve Diffie-Hellman (EECDH) key exchange. See smtpd_tls_eecdh_grade for further details.

      +

      This feature is deprecated as of Postfix 3.9. Do not specify.

      +

      This feature is available in Postfix 2.8 and later.

      %PARAM tlsproxy_tls_exclude_ciphers $smtpd_tls_exclude_ciphers @@ -15772,6 +15987,9 @@ shared by all three services, namely smtpd_tls_session_cache_timeout.

      but do not require that clients use TLS encryption. See smtpd_use_tls for further details. Use tlsproxy_tls_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_tls_security_level instead.

      +

      This feature is available in Postfix 2.8 and later.

      %PARAM smtpd_reject_footer @@ -17575,6 +17793,9 @@ was previously called tlsproxy_client_level.

      usage policy by next-hop destination and by remote TLS server hostname. See smtp_tls_per_site for further details.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_policy_maps instead.

      +

      This feature is available in Postfix 3.4 and later.

      %PARAM tlsproxy_client_policy $smtp_tls_policy_maps @@ -17601,6 +17822,9 @@ was previously called tlsproxy_client_policy.

      support. See smtp_use_tls for further details. Use tlsproxy_client_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_security_level instead.

      +

      This feature is available in Postfix 3.4 and later.

      %PARAM tlsproxy_client_enforce_tls $smtp_enforce_tls @@ -17609,6 +17833,9 @@ tlsproxy_client_security_level instead.

      See smtp_enforce_tls for further details. Use tlsproxy_client_security_level instead.

      +

      This feature is deprecated as of Postfix 3.9. Specify +tlsproxy_client_security_level instead.

      +

      This feature is available in Postfix 3.4 and later.

      %PARAM smtpd_tls_chain_files @@ -18145,6 +18372,17 @@ default suffix, YYYYMMDD-HHMMSS, allows logs to be rotated frequently.

      This feature is available in Postfix 3.4 and later.

      +%PARAM maillog_file_permissions 0600 + +

      The file access permissions that will be set when the file +$maillog_file is created for the first time, or when the file is +created after an existing file is rotated. Specify one of: 0600 +(only super-user read/write access), 0640 (adds 'group' read +access), or 0644 (also adds 'other' read access). The leading +'0' is optional.

      + +

      This feature is available in Postfix 3.9 and later.

      + %PARAM info_log_address_format external

      The email address form that will be used in non-debug logging @@ -18495,6 +18733,140 @@ configuration parameter. See there for details.

      This feature is available in Postfix 3.7 and later.

      +%PARAM smtpd_tls_enable_rpk no + +

      Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking for or requiring client +authentication. This feature is ignored when there is no raw public +key support in the local TLS implementation.

      + +

      The Postfix SMTP server will log a warning when "smtpd_tls_enable_rpk += yes", but the remote SMTP client sends a certificate, the +certificate's public key fingerprint does not match a check_ccert_access +table, while the certificate fingerprint does match a check_ccert_access +table. The remote SMTP client would lose access when it starts +sending a raw public key instead of a certificate, after its TLS +implementation is updated with raw public key support.

      + +

      The Postfix SMTP server always sends a raw public key instead +of a certificate, if solicited by the remote SMTP client and the +local TLS implementation supports raw public keys. If the client +sends a server name indication with an SNI TLS extension, and +tls_server_sni_maps is configured, the server will extract a raw +public key from the indicated certificate.

      + +

      Sample commands to compute certificate and public key SHA256 digests:

      + +
      +# SHA256 digest of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -pubkey -noout |
      +    openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first private key in "pkey.pem"
      +$ openssl pkey -in pkey.pem -pubout -outform DER |
      +    openssl dgst -sha256 -c
      +
      + +

      This feature is available in Postfix 3.9 and later.

      + +%PARAM tlsproxy_tls_enable_rpk $smtpd_tls_enable_rpk + +

      Request that remote SMTP clients send an RFC7250 raw public key +instead of an X.509 certificate, when asking or requiring client +authentication. See $smtpd_tls_enable_rpk for details.

      + +

      This feature is available in Postfix 3.9 and later.

      + +%PARAM smtp_tls_enable_rpk no + +

      Request that remote SMTP servers send an RFC7250 raw public key +instead of an X.509 certificate. This feature and the enable_rpk +policy attribute are ignored when there is no raw public key support +in the local TLS implementation.

      + +
        + +
      • At the "may", "encrypt" and "fingerprint" security levels, +with parameter setting "smtp_tls_enable_rpk = yes" or with "enable_rpk += yes" in a policy entry, the Postfix SMTP client will indicate in +the TLS handshake that it prefers to receive a raw server public +key, but it will still accept a server public key certificate.

        + +
      • At the "fingerprint" security level, with parameter setting +"smtp_tls_enable_rpk = yes" or with "enable_rpk = yes" in a policy +entry, server authentication based on certificate fingerprints +becomes more fragile. Even if the server private key and certificate +remain unchanged, the remote SMTP server will fail fingerprint +authentication (won't match the configured list of fingerprints) +when it starts sending a raw public key instead of a certificate, +after its TLS implementation is updated with raw public key support. +Therefore, DO NOT enable raw public keys to remote destinations +authenticated by server certificate fingerprints. You should +enable raw public keys only for servers matched via their public +key fingerprint.

        + +
      • At the "verify" and "secure" security levels, the Postfix +SMTP client always ignores the parameter setting smtp_tls_enable_rpk +or the enable_rpk policy attribute.

        + +
      • At the opportunistic "dane" security level, the Postfix +SMTP client ignores the parameter setting smtp_tls_enable_rpk or +the enable_rpk policy attribute (but it will respect them when it +falls back to the "may" or "encrypt" level). When all valid TLSA +records specify only server public keys (no certificates) and the +local TLS implementation supports raw public keys, the client will +indicate in the TLS handshake that it prefers to receive a raw +public key, but it will still accept a public key certificate.

        + +
      • At the mandatory "dane-only" security level, the Postfix +SMTP client always ignores the parameter setting smtp_tls_enable_rpk +or the enable_rpk policy attribute. When all valid TLSA records +specify only server public keys (no certificates) and the local TLS +implementation supports raw public keys, the client will indicate +in the TLS handshake that it prefers to receive a raw public key, +but it will still accept a public key certificate.

        + +
      + +

      The Postfix SMTP client is always willing to send raw public keys +to servers that solicit them when a client certificate is configured +and the local TLS implementation supports raw public keys.

      + +

      Sample commands to compute certificate and public key SHA256 digests:

      + +
      +# SHA256 digest of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first certificate in "cert.pem"
      +$ openssl x509 -in cert.pem -pubkey -noout |
      +    openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
      +
      + +
      +# SHA256 digest of the SPKI of the first private key in "pkey.pem"
      +$ openssl pkey -in pkey.pem -pubout -outform DER |
      +    openssl dgst -sha256 -c
      +
      + +

      This feature is available in Postfix 3.9 and later.

      + +%PARAM lmtp_tls_enable_rpk yes + +

      The LMTP-specific version of the smtp_tls_enable_rpk +configuration parameter. See there for details.

      + +

      This feature is available in Postfix 3.9 and later.

      + %PARAM use_srv_lookup

      Enables discovery for the specified service(s) using DNS SRV @@ -18629,8 +19001,7 @@ via the tls_config_file parameter. When empty, or when the selected name is not present in the configuration file, the default application name ("openssl_conf") is used as a fallback.

      -

      This feature is available in Postfix ≥ 3.9, 3.8.1, 3.7.6, -3.6.10, and 3.5.20.

      +

      This feature is available in Postfix ≥ 3.9.

      %PARAM tls_config_file default @@ -18719,7 +19090,7 @@ MinProtocol = TLSv1

      This feature is available in Postfix ≥ 3.9, 3.8.1, 3.7.6, 3.6.10, and 3.5.20.

      -%PARAM smtpd_forbid_bare_newline Postfix < 3.9: no +%PARAM smtpd_forbid_bare_newline Postfix ≥ 3.9: normalize

      Reject or restrict input lines from an SMTP client that end in <LF> instead of the standard <CR><LF>. Such line @@ -18732,7 +19103,8 @@ SMTP smuggling.

      -
      normalize
      Require the standard +
      normalize (default for Postfix ≥ 3.9)
      +
      Require the standard End-of-DATA sequence <CR><LF>.<CR><LF>. Otherwise, allow command or message content lines ending in the non-standard <LF>, and process them as if the client sent the @@ -18744,6 +19116,13 @@ with the standard End-of-DATA sequence <CR><LF>.<CR><LF>.

      Such clients can be excluded with smtpd_forbid_bare_newline_exclusions.
      +
      note
      Same as "normalize", but also notes in +the log whether the Postfix SMTP server received any lines with +"bare <LF>". The information is formatted as "disconnect +from name[address] ... notes=bare_lf". The notes value is +expected to become a list of comma-separated names.

      This +feature is available in Postfix 3.9 and later.
      +
      yes
      Compatibility alias for normalize.
      reject
      Require the standard End-of-DATA @@ -18762,8 +19141,8 @@ of BDAT violations, BDAT can be selectively disabled with smtpd_discard_ehlo_keyword_address_maps, or globally disabled with smtpd_discard_ehlo_keywords).
      -
      no (default)
      Do not require the standard -End-of-DATA +
      no (default for Postfix < 3.9)
      +
      Do not require the standard End-of-DATA sequence <CR><LF>.<CR><LF>. Always process a bare <LF> as if the client sent <CR><LF>. This option is fully backwards compatible, but is not recommended for @@ -18889,9 +19268,24 @@ implementation-dependent manner.

      Disconnect remote SMTP clients that violate RFC 2920 (or 5321) command pipelining constraints. The server replies with "554 5.5.0 Error: SMTP protocol synchronization" and logs the unexpected remote -SMTP client input. Specify "smtpd_forbid_unauth_pipelining = yes" -to enable. This feature is enabled by default with Postfix ≥ -3.9.

      +SMTP client input. This feature is enabled by default with Postfix +≥ 3.9. Specify "smtpd_forbid_unauth_pipelining = no" to disable. +

      This feature is available in Postfix ≥ 3.9, 3.8.1, 3.7.6, 3.6.10, and 3.5.20.

      + +%PARAM force_mime_input_conversion no + +

      Convert body content that claims to be 8-bit into quoted-printable, +before header_checks, body_checks, Milters, and before after-queue +content filters. This feature does not affect messages that are +sent into smtpd_proxy_filter.

      + +

      The typical use case is an MTA that applies this conversion +before signing outbound messages, so that the signatures will remain +valid when a message is later delivered to an MTA that does not +announce 8BITMIME support, or when a message line exceeds the SMTP +length limit.

      + +

      This feature is available in Postfix ≥ 3.9.

      diff --git a/proto/regexp_table b/proto/regexp_table index 1c38472..5e8c15f 100644 --- a/proto/regexp_table +++ b/proto/regexp_table @@ -147,9 +147,14 @@ # # Postfix parses the result as if it is a file in /etc/postfix. # -# Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep -# Postfix from trying to do \fI$name\fR expansion as it -# evaluates a parameter value. +# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +# to keep Postfix from trying to do \fI$name\fR expansion as +# it evaluates a parameter value. +# +# Note: when using \fI$name\fR inside an inlined pattern, +# this will not disable metacharacters such as '.' in the +# \fI$name\fR expansion. To prevent unexpected matches, use +# a pcre: table, and specify \eQ\fI$name\fR\eE. # EXAMPLE SMTPD ACCESS MAP # # Disallow sender-specified routing. This is a must if you relay mail # # for other domains. diff --git a/proto/relocated b/proto/relocated index a0a54ca..b517b35 100644 --- a/proto/relocated +++ b/proto/relocated @@ -125,8 +125,8 @@ # .PP # Other parameters of interest: # .IP "\fBinet_interfaces (all)\fR" -# The network interface addresses that this mail system receives -# mail on. +# The local network interface addresses that this mail system +# receives mail on. # .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" # The list of domains that are delivered via the $local_transport # mail delivery transport. @@ -134,7 +134,7 @@ # The domain name that locally-posted mail appears to come # from, and that locally posted mail is delivered to. # .IP "\fBproxy_interfaces (empty)\fR" -# The network interface addresses that this mail system receives mail +# The remote network interface addresses that this mail system receives mail # on by way of a proxy or network address translation unit. # SEE ALSO # trivial-rewrite(8), address resolver diff --git a/proto/socketmap_table b/proto/socketmap_table index be01054..52d1f47 100644 --- a/proto/socketmap_table +++ b/proto/socketmap_table @@ -13,7 +13,7 @@ # \fBpostmap -q - socketmap:unix:\fIpathname\fB:\fIname\fB <\fIinputfile\fR # DESCRIPTION # The Postfix mail system uses optional tables for address -# rewriting. mail routing or policy lookup. +# rewriting, mail routing or policy lookup. # # The Postfix socketmap client expects TCP endpoint names of # the form \fBinet:\fIhost\fB:\fIport\fB:\fIname\fR, or diff --git a/proto/stop b/proto/stop index 0ad3511..beec6d2 100644 --- a/proto/stop +++ b/proto/stop @@ -1182,7 +1182,6 @@ Nexthop OP OTIFY OpenSSL's -Postix Pt SECG SSLEAY @@ -1577,3 +1576,37 @@ Korbar ffdhe srv stderr +charset +latin +utf +mb +SPKI +certificate's +pubout +rpk +sni +Amawalk +resychronization +ENVID +netcat +probers +lf +EOD +chunking +allowlists +FWS +mongodb +Aionda +Ferraro +GmbH +Hamid +LLC +Maadani +GTEST +MONGODB +MongoDB +Sakaguchi +Toshifumi +envid +manpages +rr diff --git a/proto/stop.double-cc b/proto/stop.double-cc index 8efd133..bff4534 100644 --- a/proto/stop.double-cc +++ b/proto/stop.double-cc @@ -333,3 +333,5 @@ void void cleanup_milter_receive state count Available in in Postfix version 2 3 3 7 length length of 0 31 0 127 address address string length + whether the standard End of DATA sequence CRLF CRLF is required and + Require CRLF CRLF diff --git a/proto/stop.double-history b/proto/stop.double-history index c1026c8..f6df421 100644 --- a/proto/stop.double-history +++ b/proto/stop.double-history @@ -12,7 +12,6 @@ Fix by Viktor Dukhovni Files tls tls h tls tls_dane c Discovered by Benny Pedersen File postscreen postscreen c proto postconf proto src tlsproxy tlsproxy c src smtpd smtpd c - proto postconf proto src tlsproxy tlsproxy c src smtpd smtpd c src tls tls h src tls tls_proxy_client_misc c src tls tls_misc c src global mail_params h src smtp smtp c attacks Fix by Viktor Dukhovni Files tls tls h tls_client c @@ -25,18 +24,98 @@ arguments Files src dns dns h src dns dns_rr_eq_sa c only a subset of all arguments Files src dns dns h global mail_params h smtp smtp c smtpd smtpd c tls tls_misc c - global mail_params h smtp smtp c smtpd smtpd c tls tls_misc c tls tls_proxy_client_scan c tls tls_proxy h tlsproxy tlsproxy c smtp smtp c smtpd smtpd c tls tls_misc c - smtp smtp c smtpd smtpd c tls tls_misc c proto proto SASL_README html proto SQLITE_README html proto postconf proto global mail_params h smtp smtp c smtpd smtpd c tls tls_misc c tls tls_proxy_client_misc c tls tls_proxy h tlsproxy tlsproxy c postfix postfix c postlog postlog c - postfix postfix c postlog postlog c util net_mask_top hc smtpd smtpd c smtpd smtpd_peer c util inet_prefix_top hc smtpd smtpd c smtpd smtpd_peer c File smtp smtp h manpage File postscreen postscreen c Files postconf postconf h postconf postconf_dbms c +proto proto ADDRESS_REWRITING_README html + proto postconf proto proto ADDRESS_REWRITING_README html + cleanup cleanup c local local c smtpd smtpd c + postfix postfix c + aliasing Files proto aliases proto virtual postfix postfix c +proto proto aliases proto virtual proto ADDRESS_REWRITING_README html + master master c postlog postlog c postlogd postlogd c + proto postconf proto proto aliases proto virtual + posttls finger posttls finger c smtp smtp c smtp smtp_proto c + tls tls_client c tls tls h tls tls_misc c + tls tls_proxy h tls tls_server c tlsproxy tlsproxy c + Cleanup removed some the the instances Files + clients Files posttls finger posttls finger c smtp smtp c + smtp smtp c smtp smtp_proto c tls tls_client c tls tls h + smtp smtp c smtpd smtpd c tls tls_client c tls tls h + smtp smtp_proto c tls tls h tls tls_proxy_client_misc c + tls tls_server c tlsproxy tlsproxy c + tlsproxy tlsproxy c + proto postconf proto smtp smtp c smtpd smtpd c + pipelining before the server greeting File smtpd smtpd c + before the server greeting File smtpd smtpd c + global mail_params h smtpd smtpd c proto postconf proto + Typo fix by Trent W Buck Files proto postconf proto proto stop + smtp smtp c smtp smtp h smtp smtp_params c smtp smtp_proto c + smtp smtp_tls_policy c smtpd smtpd c smtpd smtpd_check c + tls tls h tls tls_client c tls tls_dane c tls tls_fprint c + reported by Serg File smtp smtp h + smtp lmtp_params c smtp smtp c smtp smtp_params c + plaintext Problem reported by Serg File smtp smtp h + cleanup cleanup c cleanup cleanup_init c proto postconf proto + smtpd smtpd c + proto postconf proto postscreen postscreen c + global maillog_client c master master c smtp smtp c + src postalias postalias c src postmap postmap c + src postalias postalias c src postmap postmap c + src smtpd smtpd c src smtpd smtpd_check c + not proxymap or proxywrite File proxymap proxymap c + still has its all zero SIZE record File postcat postcat c + manpage text File smtp smtp c + manpage text Files smtp smtp c global mail_proto h + File proxymap proxymap c + on process name Files smtp smtp c global mail_proto h + client process name File proxymap proxymap c + available Files local command c local local c + ID if available File pipe pipe c + global smtp_stream h smtpd smtpd c + global smtp_stream c global smtp_stream h smtpd smtpd c + log the helo mail and rcpt information Files smtpd smtpd c + LF LF or LF CR LF before responding This increases + smtpd smtpd c global smtp_stream hc global cleanup_user h + smtpd smtpd c smtpd smtpd_check c + keep reading message content after an unexpected LF LF + forms Files proto postconf proto smtpd smtpd c + CR LF CR CR LF File global smtp_stream c + CR LF CR CR LF There is no smuggling vulnerability + sequence mail systems send CR LF CR CR LF instead + global mail_params h cleanup cleanup c cleanup cleanup_message c + Files smtpd smtpd c proto postconf proto RELEASE_NOTES + stable releases Files global smtp_stream hc smtpd smtpd c + Files global smtp_stream hc smtpd smtpd c + Files smtpd smtpd c proto postconf proto + names Files smtpd smtpd hc + or access control limitations Files smtpd smtpd hc + spam the log with a warning message File tlsmgr tlsmgr c + Cleanup tlsmgr c fix 20240124 File tlsmgr tlsmgr c + MX or SRV records File smtp smtp c + a list of comma separated names Files smtpd smtpd hc + dnsblog dnsblog c postkick postkick c postlock postlock c + postdrop postdrop c postsuper postsuper c sendmail sendmail c + postlogd postlogd c + qmgr qmgr c qmqpd qmqpd c trivial rewrite trivial rewrite c + strategies File smtp smtp c + postconf postconf c postconf postconf_dbms c postconf postconf h + postconf postconf c postconf postconf_unused c + postfix start start fg check reload status Files + Files postconf postconf c postconf postconf_unused c + the commands postfix start start fg check reload or + status Files postconf postconf c postconf postconf_dbms c + postconf postconf h conf postfix script conf post install + postconf postconf c postconf postconf_dbms c + File tlsmgr tlsmgr c + restrictions Files dns dns h dns dns_lookup c dns dns_rr c + systems 6 bytes for LP64 File dns dns h diff --git a/proto/stop.double-install-proto-text b/proto/stop.double-install-proto-text index 338286e..4e3f43d 100644 --- a/proto/stop.double-install-proto-text +++ b/proto/stop.double-install-proto-text @@ -39,3 +39,7 @@ root root you shlib_directory shlib_directory user foo domain user domain domain virtual virtual alias domain anything right hand content does not matter + skipping unexpected LF LF in DATA from +Inbound SMTP smuggling strip extra CR in CR LF CR CR LF +Inbound SMTP smuggling don t strip extra CR in CR LF CR CR LF + CR LF CR CR LF to silence false alarms from test tools diff --git a/proto/stop.double-proto-html b/proto/stop.double-proto-html index c216f95..a4b2332 100644 --- a/proto/stop.double-proto-html +++ b/proto/stop.double-proto-html @@ -42,7 +42,6 @@ dd dd The default algorithm is b sha256 b with Postfix ge 3 6 dd No TLS TLS will not be used unless enabled for specific Dec 4 04 30 09 hostname postfix smtpd 58549 NOQUEUE reject default_transport uucp uucp gateway - different client IP addresses Lookup results override the the global Documentation Documentation is available as README files start with the file done done done done @@ -202,8 +201,6 @@ smtp_tls_mandatory_protocols SSLv2 SSLv3 TLSv1 TLSv1 1 SSLv3 TLSv1 TLSv1 1 TLSv1 2 and TLSv1 3 Starting with T 5 10 20 40 80 160 320 640 1280 1280 T A 5 10 20 40 80 160 320 320 - The and match and literally Without the the - The matches literally Without the the would Therefore 301 0301 0x301 and 0x0301 are all equivalent to The syntax of name value value name value and name value the the backed up domain tld domain This prevents your mail queue @@ -246,3 +243,118 @@ dt dt b name value b Postfix ge 3 0 dt parametername stress something something Other p Note on OpenBSD systems specify dev dev arandom when dev dev urandom user3 example net smtp smtp relay example net submission + virtual_alias_maps hash etc postfix virtual virtual aliasing +system_wide_settings system_wide_settings +ssl_library_settings ssl_library_settings +initial_ssl_settings initial_ssl_settings +postfix_settings postfix_settings +postfix_ssl_settings postfix_ssl_settings +baseline_postfix_settings baseline_postfix_settings + The and match and literally Without the the + The matches literally Without the the would + The example is simplified for educational purposes In reality my patterns list multiple domain names as domain domain + The matches literally Without the the would match any character + The and match and literally Without the the and would be grouping operators + The matches literally Without the the would match any character + pipeline all commands following EHLO for example MAIL RCPT BDAT BDAT MAIL RCPT BDAT without ever having to wait for a server response This means that with BDAT the Postfix SMTP server cannot distinguish between a well behaved client and a + NOTE Postfix 3 6 also introduces support for the level level and other operators to compare compatibility levels With the standard operators etc compatibility level 3 10 would be smaller than 3 9 which is undesirable + Otherwise the benefits of SMTP connection caching are minor it eliminates the latency of the TCP handshake SYN SYN ACK ACK plus the latency of the SMTP initial handshake 220 greeting EHLO command EHLO response With TLS encrypted + Otherwise the benefits of SMTP connection caching are minor it eliminates the latency of the TCP handshake SYN SYN ACK ACK plus the latency of the SMTP initial handshake 220 greeting EHLO command EHLO response With TLS encrypted + 3 Reject the mail by sending a suitable status code back to Postfix Postfix will send the mail back to the sender address + Line 8 NEVER NEVER NEVER use the t command line option here It will mis deliver mail like sending messages from a mailing list back to the mailing list + Line 8 NEVER NEVER NEVER use the t command line option here It will mis deliver mail like sending messages from a mailing list back to the mailing list +Documentation Documentation is available as README files start with the file README_FILES AAAREADME as HTML web pages point your browser to html index html and as UNIX style manual pages + Parameters whose defaults can be specified in this way are listed below See the postconf 5 manpage for a description command nroff man man man5 postconf 5 less + Parameters whose defaults can be specified in this way are listed below See the postconf 5 manpage for a description command nroff man man man5 postconf 5 less +mynetworks mynetworks 127 0 0 0 8 168 100 189 0 28 1 128 fe80 10 2001 240 587 64 +Postfix Postfix can use an LDAP directory as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated network database with fine grained access controls By not + If you re using the libraries from the UM distribution http www umich edu dirsvcs ldap ldap html or OpenLDAP http www openldap org something like this in the top level of your Postfix source tree should work +query_filter mailacceptinggeneralid s maildrop maildrop maildrop +query_filter mailacceptinggeneralid s maildrop maildrop maildrop +query_filter mailacceptinggeneralid s maildrop maildrop maildrop owner cn root dc your dc com +query_filter mailacceptinggeneralid s maildrop maildrop maildrop owner cn root dc your dc com + As of Postfix version 2 0 the Postfix SMTP server rejects mail for unknown recipients in local domains domains that match mydestination or the IP addresses in inet_interfaces or proxy_interfaces with User unknown in local recipient table + Postfix emulates a limited number of Sendmail macros as shown in the table Some macro values depend on whether a recipient is rejected rejected recipients are available on request by the Milter application Different macros are available at + Postfix has TWO sets of mail filters filters that are used for SMTP mail only specified with the smtpd_milters parameter and filters for non SMTP mail specified with the non_smtpd_milters parameter The non SMTP filters are primarily for + etc usr usr bin var var spool and so on This is especially an issue if you executed postfix install see above as an unprivileged user + etc usr usr bin var var spool and so on This is especially an issue if you executed postfix install see above as an unprivileged user + parametername stress something stress something or parametername stress something something Other parameters always evaluate as if the stress value is the empty string + parametername stress something stress something or parametername stress something something Other parameters always evaluate as if the stress value is the empty string + more CPU faster disks and more network bandwidth can deal with larger deferred queues but as a rule of thumb the deferred queue scales to somewhere between 100 000 and 1 000 000 messages with good performance unlikely above that limit + 31 sasldb Accounts are stored stored in a Cyrus SASL Berkeley DB database + assigned to the delivery slots might look like this 12131415 Hmm fine for sneaking in the single recipient mail but how do we sneak in the mail with more than one recipient Say if we have one four recipient mail followed by two two recipient + we see the hundred recipient job can accumulate ten free delivery slots and then we could preempt it and sneak in the ten recipient mail Wait wait wait Could we Aren t we overinflating the original one thousand recipient mail + The truth is that it turns out that it is not really necessary to wait until the jobs counter accumulates all the delivery slots in advance Say we have ten recipient mail followed by two two recipient mails If the preemption happened when enough + Disallowing RFC 822 address syntax example MAIL FROM the dude dude example com + 3 Reject the mail by sending a suitable SMTP status code back to Postfix Postfix passes the status back to the remote SMTP client This way Postfix does not have to send a bounce message + Lines 14 18 Define the list of valid addresses in the the backed up domain tld domain This prevents your mail queue from filling up with undeliverable MAILER DAEMON messages If you can t maintain a list of valid recipients then you must + The syntax of name value value name value and name value is explained at the beginning of the postconf 5 manual page + Use 521 SMTP reply codes Postfix 2 6 and later or 421 Postfix 2 3 2 5 to hang up on clients that that match botnet related RBLs see next bullet or that match selected non RBL restrictions such as SMTP access maps The Postfix SMTP + the next hop destination can have the Postfix specific form name name port name or name port + dt b a name no_unknown_recipient_checks no_unknown_recipient_checks a b dt + dt b a name check_ccert_access check_ccert_access a i a href DATABASE_README html type table a i b dt + dt b a name check_client_access check_client_access a i a href DATABASE_README html type table a i b dt + dt b a name check_client_a_access check_client_a_access a i a href DATABASE_README html type table a i b dt + dt b a name check_client_mx_access check_client_mx_access a i a href DATABASE_README html type table a i b dt + dt b a name check_client_ns_access check_client_ns_access a i a href DATABASE_README html type table a i b dt + dt b a name check_reverse_client_hostname_access check_reverse_client_hostname_access a i a href DATABASE_README html type table a i b dt + dt b a name check_reverse_client_hostname_a_access check_reverse_client_hostname_a_access a i a href DATABASE_README html type table a i b dt + dt b a name check_reverse_client_hostname_mx_access check_reverse_client_hostname_mx_access a i a href DATABASE_README html type table a i b dt + dt b a name check_reverse_client_hostname_ns_access check_reverse_client_hostname_ns_access a i a href DATABASE_README html type table a i b dt + dt b a name check_sasl_access check_sasl_access a i a href DATABASE_README html type table a i b dt + dt b a name permit_sasl_authenticated permit_sasl_authenticated a b dt + dt b a name permit_tls_all_clientcerts permit_tls_all_clientcerts a b dt + dt b a name reject_rbl_client reject_rbl_client i rbl_domain d d d d i a b dt + dt b a name permit_dnswl_client permit_dnswl_client i dnswl_domain d d d d i a b dt + dt b a name reject_rhsbl_client reject_rhsbl_client i rbl_domain d d d d i a b dt + dt b a name permit_rhswl_client permit_rhswl_client i rhswl_domain d d d d i a b dt + dt b a name reject_rhsbl_reverse_client reject_rhsbl_reverse_client i rbl_domain d d d d i a b dt + dt b a name reject_unknown_client_hostname reject_unknown_client_hostname a b with Postfix lt 2 3 reject_unknown_client dt + dt b a name reject_unknown_reverse_client_hostname reject_unknown_reverse_client_hostname a b dt + dt b a name reject_unknown_forward_client_hostname reject_unknown_forward_client_hostname a b dt + dt b a name check_policy_service check_policy_service i servername i a b dt + dt b a name reject_multi_recipient_bounce reject_multi_recipient_bounce a b dt + dt b a name check_etrn_access check_etrn_access a i a href DATABASE_README html type table a i b dt + dt b a name check_helo_access check_helo_access a i a href DATABASE_README html type table a i b dt + dt b a name check_helo_a_access check_helo_a_access a i a href DATABASE_README html type table a i b dt + dt b a name check_helo_mx_access check_helo_mx_access a i a href DATABASE_README html type table a i b dt + dt b a name check_helo_ns_access check_helo_ns_access a i a href DATABASE_README html type table a i b dt + dt b a name reject_invalid_helo_hostname reject_invalid_helo_hostname a b with Postfix lt 2 3 reject_invalid_hostname dt + dt b a name reject_non_fqdn_helo_hostname reject_non_fqdn_helo_hostname a b with Postfix lt 2 3 reject_non_fqdn_hostname dt + dt b a name reject_rhsbl_helo reject_rhsbl_helo i rbl_domain d d d d i a b dt + dt b a name reject_unknown_helo_hostname reject_unknown_helo_hostname a b with Postfix lt 2 3 reject_unknown_hostname dt + dt b a name check_recipient_access check_recipient_access a i a href DATABASE_README html type table a i b dt + dt b a name check_recipient_a_access check_recipient_a_access a i a href DATABASE_README html type table a i b dt + dt b a name check_recipient_mx_access check_recipient_mx_access a i a href DATABASE_README html type table a i b dt + dt b a name check_recipient_ns_access check_recipient_ns_access a i a href DATABASE_README html type table a i b dt + dt b a name reject_non_fqdn_recipient reject_non_fqdn_recipient a b dt + dt b a name reject_rhsbl_recipient reject_rhsbl_recipient i rbl_domain d d d d i a b dt + dt b a name reject_unauth_destination reject_unauth_destination a b dt + dt b a name reject_unknown_recipient_domain reject_unknown_recipient_domain a b dt + dt b a name reject_unlisted_recipient reject_unlisted_recipient a b with Postfix version 2 0 check_recipient_maps dt + dt b a name reject_unverified_recipient reject_unverified_recipient a b dt + dt b a name check_sender_access check_sender_access a i a href DATABASE_README html type table a i b dt + dt b a name check_sender_a_access check_sender_a_access a i a href DATABASE_README html type table a i b dt + dt b a name check_sender_mx_access check_sender_mx_access a i a href DATABASE_README html type table a i b dt + dt b a name check_sender_ns_access check_sender_ns_access a i a href DATABASE_README html type table a i b dt + dt b a name reject_authenticated_sender_login_mismatch reject_authenticated_sender_login_mismatch a b dt + dt b a name reject_known_sender_login_mismatch reject_known_sender_login_mismatch a b dt + dt b a name reject_rhsbl_sender reject_rhsbl_sender i rbl_domain d d d d i a b dt + dt b a name reject_sender_login_mismatch reject_sender_login_mismatch a b dt + dt b a name reject_unauthenticated_sender_login_mismatch reject_unauthenticated_sender_login_mismatch a b dt + dt b a name reject_unknown_sender_domain reject_unknown_sender_domain a b dt + dt b a name check_address_map check_address_map a i a href DATABASE_README html type table a i b dt + PARAM postscreen_dnsbl_max_ttl postscreen_dnsbl_ttl postscreen_dnsbl_ttl 1 h +standard lt CR gt lt LF gt br br This maintains compatibility + lt CR gt lt LF gt lt CR gt lt LF gt br br Such clients + smtpd_forbid_bare_newline_reject_code br br This will reject + br br This will also reject some email from Microsoft services +2045 Sections 2 7 and 2 8 br br Such clients can be excluded + br br This will also reject email from services that use BDAT +RFC 2045 Sections 2 7 and 2 8 br br Such clients can be +to become a list of comma separated names br br This feature +the form of a domain name hostname hostname service hostname service +expected to become a list of comma separated names br br This +Postfix Postfix can use MongoDB as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated noSQL database with fine grained access controls By not storing it + CCARGS CCARGS DHAS_MONGODB I usr include libmongoc 1 0 + dt dt dd 2 Also enable verbose logging in the Postfix TLS diff --git a/proto/stop.spell-cc b/proto/stop.spell-cc index 3da6690..097c7ac 100644 --- a/proto/stop.spell-cc +++ b/proto/stop.spell-cc @@ -1386,7 +1386,6 @@ th tha thash THASH -theadsafe threadsafe thusly timecmp @@ -1443,7 +1442,7 @@ tv txn TXT Typechecking -TYPECONNSTRING +TYPECONNSTR typedef typedefs TYPEINET @@ -1801,3 +1800,42 @@ bitcount bytecount ipproto cw +uncreate +MFLAGS +CRED +RPK +RPKs +SPKI +peerpkey +rpk +ep +inlined +stringz +Sarvepalli +uXXXX +Aionda +Ferraro +GmbH +Hamid +LLC +Maadani +MongoDB +PRId +bson +dexo +hamid +itoa +libmongoc +mongdb +mongo +mongodb +mongodbconf +Dextrous +Mongo +SUD +qtype +depr +dfhHnopqvx +fhHoqvx +foqvx +ILP diff --git a/proto/stop.spell-history b/proto/stop.spell-history index 096da09..6b009ed 100644 --- a/proto/stop.spell-history +++ b/proto/stop.spell-history @@ -56,3 +56,23 @@ Valgrind Florian Piekert refactored +Fumiyasu +SATOH +INI +Serg +Kinzler +smtpstone +spammy +Birta +Levente +MariaDB +dehtml +NONPROD +LC +Philosof +MONGODB +Refactored +Vijay +Sakaguchi +Toshifumi +mxonly diff --git a/proto/stop.spell-proto-html b/proto/stop.spell-proto-html index 1912240..79c1ce5 100644 --- a/proto/stop.spell-proto-html +++ b/proto/stop.spell-proto-html @@ -357,3 +357,20 @@ kDHE srv wraptls api +MinProtocol +spammy +concat +hamid +ina +lbson +libbson +libmobgo +libmongoc +lmongoc +mongo +mongod +noSQL +srv +viktor +MONGODB +MongoDB diff --git a/proto/virtual b/proto/virtual index 6e32881..e1935f0 100644 --- a/proto/virtual +++ b/proto/virtual @@ -10,13 +10,14 @@ # # \fBpostmap -q - /etc/postfix/virtual <\fIinputfile\fR # DESCRIPTION -# The optional \fBvirtual\fR(5) alias table rewrites recipient -# addresses for all local, all virtual, and all remote mail -# destinations. -# This is unlike the \fBaliases\fR(5) table which is used -# only for \fBlocal\fR(8) delivery. This feature is implemented +# The optional \fBvirtual\fR(5) alias table (virtual_alias_maps) +# applies to all recipients: local(8), virtual, and remote. +# This feature is implemented # in the Postfix \fBcleanup\fR(8) daemon before mail is queued. # +# This is unlike the \fBaliases\fR(5) table (alias_maps) which +# applies only to \fBlocal\fR(8) recipients. +# # Virtual aliasing is recursive; to terminate recursion for # a specific address, alias that address to itself. # @@ -244,8 +245,9 @@ # and for default values. Use the "\fBpostfix reload\fR" command after # a configuration change. # .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" -# Optional lookup tables that alias specific mail addresses or domains -# to other local or remote addresses. +# Optional lookup tables with aliases that apply to all recipients: +# \fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +# only to \fBlocal\fR(8) recipients. # .IP "\fBvirtual_alias_domains ($virtual_alias_maps)\fR" # Postfix is the final destination for the specified list of virtual # alias domains, that is, domains for which all addresses are aliased @@ -256,8 +258,8 @@ # .PP # Other parameters of interest: # .IP "\fBinet_interfaces (all)\fR" -# The network interface addresses that this mail system receives -# mail on. +# The local network interface addresses that this mail system +# receives mail on. # .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" # The list of domains that are delivered via the $local_transport # mail delivery transport. @@ -270,7 +272,7 @@ # \fIlistname\fR-request address localparts when the recipient_delimiter # is set to "-". # .IP "\fBproxy_interfaces (empty)\fR" -# The network interface addresses that this mail system receives mail +# The remote network interface addresses that this mail system receives mail # on by way of a proxy or network address translation unit. # SEE ALSO # cleanup(8), canonicalize and enqueue mail diff --git a/src/bounce/bounce_notify_util.c b/src/bounce/bounce_notify_util.c index 781a525..2482359 100644 --- a/src/bounce/bounce_notify_util.c +++ b/src/bounce/bounce_notify_util.c @@ -773,15 +773,14 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) post_mail_fprintf(bounce, "X-%s-Queue-ID: %s", bounce_info->mail_name, bounce_info->queue_id); -#define IS_UTF8_ADDRESS(str, len) \ - ((str)[0] != 0 && !allascii(str) && valid_utf8_string((str), (len))) +#define IS_UTF8_ADDRESS(str) \ + ((str)[0] != 0 && !allascii(str) && valid_utf8_stringz(str)) /* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */ if (VSTRING_LEN(bounce_info->sender) > 0) post_mail_fprintf(bounce, "X-%s-Sender: %s; %s", bounce_info->mail_name, bounce_info->smtputf8 - && IS_UTF8_ADDRESS(STR(bounce_info->sender), - VSTRING_LEN(bounce_info->sender)) ? + && IS_UTF8_ADDRESS(STR(bounce_info->sender)) ? "utf-8" : "rfc822", STR(bounce_info->sender)); if (bounce_info->arrival_time > 0) post_mail_fprintf(bounce, "Arrival-Date: %s", @@ -800,8 +799,7 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ post_mail_fprintf(bounce, "Final-Recipient: %s; %s", bounce_info->smtputf8 - && IS_UTF8_ADDRESS(rcpt->address, - strlen(rcpt->address)) ? + && IS_UTF8_ADDRESS(rcpt->address) ? "utf-8" : "rfc822", rcpt->address); /* @@ -829,8 +827,7 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ post_mail_fprintf(bounce, "Original-Recipient: %s; %s", bounce_info->smtputf8 - && IS_UTF8_ADDRESS(rcpt->orig_addr, - strlen(rcpt->orig_addr)) ? + && IS_UTF8_ADDRESS(rcpt->orig_addr) ? "utf-8" : "rfc822", rcpt->orig_addr); } post_mail_fprintf(bounce, "Action: %s", diff --git a/src/bounce/with-msgid-with-filter-no-thread.ref b/src/bounce/with-msgid-with-filter-no-thread.ref index fa30ddf..adcd507 100644 --- a/src/bounce/with-msgid-with-filter-no-thread.ref +++ b/src/bounce/with-msgid-with-filter-no-thread.ref @@ -24,7 +24,7 @@ Reporting-MTA: dns; mail.example Original-Envelope-Id: TEST-ENVID X-Postfix-Queue-ID: msgid X-Postfix-Sender: rfc822; sender@sender.example -Arrival-Date: Sat, 5 Dec 2020 13:31:48 -0500 (EST) +Arrival-Date: Sat, 05 Dec 2020 13:31:48 -0500 (EST) Final-Recipient: rfc822; rcpt-address Original-Recipient: rfc822; rcpt-orig_addr diff --git a/src/bounce/with-msgid-with-filter-with-thread.ref b/src/bounce/with-msgid-with-filter-with-thread.ref index 14d3373..ec3de87 100644 --- a/src/bounce/with-msgid-with-filter-with-thread.ref +++ b/src/bounce/with-msgid-with-filter-with-thread.ref @@ -26,7 +26,7 @@ Reporting-MTA: dns; mail.example Original-Envelope-Id: TEST-ENVID X-Postfix-Queue-ID: msgid X-Postfix-Sender: rfc822; sender@sender.example -Arrival-Date: Sat, 5 Dec 2020 13:31:48 -0500 (EST) +Arrival-Date: Sat, 05 Dec 2020 13:31:48 -0500 (EST) Final-Recipient: rfc822; rcpt-address Original-Recipient: rfc822; rcpt-orig_addr diff --git a/src/cleanup/Makefile.in b/src/cleanup/Makefile.in index 8a3c18c..b74fe0a 100644 --- a/src/cleanup/Makefile.in +++ b/src/cleanup/Makefile.in @@ -88,7 +88,9 @@ milter_tests: cleanup_milter_test bug_tests \ cleanup_milter_test15g cleanup_milter_test15h cleanup_milter_test15i \ cleanup_milter_test16a cleanup_milter_test16b cleanup_milter_test17a \ cleanup_milter_test17b cleanup_milter_test17c cleanup_milter_test17d \ - cleanup_milter_test17e cleanup_milter_test17f cleanup_milter_test17g + cleanup_milter_test17e cleanup_milter_test17f cleanup_milter_test17g \ + cleanup_milter_test18a cleanup_milter_test18b cleanup_milter_test18c \ + cleanup_milter_test18d root_tests: @@ -671,6 +673,46 @@ cleanup_milter_test17g: cleanup_milter test-queue-file17 cleanup_milter.in17g \ diff cleanup_milter.ref17g2 cleanup_milter.tmp2 rm -f test-queue-file17g.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 +cleanup_milter_test18a: cleanup_milter test-queue-file18 cleanup_milter.in18a \ + cleanup_milter.ref18a1 ../postcat/postcat cleanup_milter.ref18a2 + cp test-queue-file18 test-queue-file18a.tmp + chmod u+w test-queue-file18a.tmp + $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref18a1 cleanup_milter.tmp1 + $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18a.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref18a2 cleanup_milter.tmp2 + rm -f test-queue-file18a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test18b: cleanup_milter test-queue-file18 cleanup_milter.in18b \ + cleanup_milter.ref18b1 ../postcat/postcat cleanup_milter.ref18b2 + cp test-queue-file18 test-queue-file18b.tmp + chmod u+w test-queue-file18b.tmp + $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref18b1 cleanup_milter.tmp1 + $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18b.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref18b2 cleanup_milter.tmp2 + rm -f test-queue-file18b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test18c: cleanup_milter test-queue-file18 cleanup_milter.in18c \ + cleanup_milter.ref18c1 ../postcat/postcat cleanup_milter.ref18c2 + cp test-queue-file18 test-queue-file18c.tmp + chmod u+w test-queue-file18c.tmp + $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref18c1 cleanup_milter.tmp1 + $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18c.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref18c2 cleanup_milter.tmp2 + rm -f test-queue-file18c.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test18d: cleanup_milter test-queue-file18 cleanup_milter.in18d \ + cleanup_milter.ref18d1 ../postcat/postcat cleanup_milter.ref18d2 + cp test-queue-file18 test-queue-file18d.tmp + chmod u+w test-queue-file18d.tmp + $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref18d1 cleanup_milter.tmp1 + $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18d.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref18d2 cleanup_milter.tmp2 + rm -f test-queue-file18d.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ diff --git a/src/cleanup/cleanup.c b/src/cleanup/cleanup.c index 6fe61f8..5db42bd 100644 --- a/src/cleanup/cleanup.c +++ b/src/cleanup/cleanup.c @@ -262,10 +262,10 @@ /* Available in Postfix version 2.1 and later: /* .IP "\fBsender_bcc_maps (empty)\fR" /* Optional BCC (blind carbon-copy) address lookup tables, indexed -/* by sender address. +/* by envelope sender address. /* .IP "\fBrecipient_bcc_maps (empty)\fR" /* Optional BCC (blind carbon-copy) address lookup tables, indexed by -/* recipient address. +/* envelope recipient address. /* ADDRESS TRANSFORMATION CONTROLS /* .ad /* .fi @@ -303,8 +303,9 @@ /* .PP /* Available in Postfix version 2.0 and later: /* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" -/* Optional lookup tables that alias specific mail addresses or domains -/* to other local or remote address. +/* Optional lookup tables with aliases that apply to all recipients: +/* \fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +/* only to \fBlocal\fR(8) recipients. /* .PP /* Available in Postfix version 2.2 and later: /* .IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR" @@ -316,9 +317,10 @@ /* What addresses are subject to sender_canonical_maps address /* mapping. /* .IP "\fBremote_header_rewrite_domain (empty)\fR" -/* Don't rewrite message headers from remote clients at all when -/* this parameter is empty; otherwise, rewrite message headers and -/* append the specified domain name to incomplete addresses. +/* Rewrite or add message headers in mail from remote clients if +/* the remote_header_rewrite_domain parameter value is non-empty, +/* updating incomplete addresses with the domain specified in the +/* remote_header_rewrite_domain parameter, and adding missing headers. /* RESOURCE AND RATE CONTROLS /* .ad /* .fi @@ -365,7 +367,7 @@ /* Preliminary SMTPUTF8 support is introduced with Postfix 3.0. /* .IP "\fBsmtputf8_enable (yes)\fR" /* Enable preliminary SMTPUTF8 support for the protocols described -/* in RFC 6531..6533. +/* in RFC 6531, RFC 6532, and RFC 6533. /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. @@ -433,6 +435,12 @@ /* .IP "\fBinfo_log_address_format (external)\fR" /* The email address form that will be used in non-debug logging /* (info, warning, etc.). +/* .PP +/* Available in Postfix 3.9 and later: +/* .IP "\fBforce_mime_input_conversion (no)\fR" +/* Convert body content that claims to be 8-bit into quoted-printable, +/* before header_checks, body_checks, Milters, and before after-queue +/* content filters. /* FILES /* /etc/postfix/canonical*, canonical mapping table /* /etc/postfix/virtual*, virtual mapping table diff --git a/src/cleanup/cleanup_addr.c b/src/cleanup/cleanup_addr.c index fd8a511..f5e7d91 100644 --- a/src/cleanup/cleanup_addr.c +++ b/src/cleanup/cleanup_addr.c @@ -148,7 +148,7 @@ off_t cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) } /* Fix 20140711: Auto-detect an UTF8 sender. */ if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) - && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + && valid_utf8_stringz(STR(clean_addr))) { state->smtputf8 |= SMTPUTF8_FLAG_SENDER; /* Fix 20140713: request SMTPUTF8 support selectively. */ if (state->flags & CLEANUP_FLAG_AUTOUTF8) @@ -216,7 +216,7 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) } /* Fix 20140711: Auto-detect an UTF8 recipient. */ if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) - && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + && valid_utf8_stringz(STR(clean_addr))) { /* Fix 20140713: request SMTPUTF8 support selectively. */ if (state->flags & CLEANUP_FLAG_AUTOUTF8) state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; @@ -275,7 +275,7 @@ void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc, } /* Fix 20140711: Auto-detect an UTF8 recipient. */ if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) - && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + && valid_utf8_stringz(STR(clean_addr))) { /* Fix 20140713: request SMTPUTF8 support selectively. */ if (state->flags & CLEANUP_FLAG_AUTOUTF8) state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; diff --git a/src/cleanup/cleanup_init.c b/src/cleanup/cleanup_init.c index 369a019..446ddf2 100644 --- a/src/cleanup/cleanup_init.c +++ b/src/cleanup/cleanup_init.c @@ -174,6 +174,7 @@ int var_auto_8bit_enc_hdr; /* auto-detect 8bit encoding header */ int var_always_add_hdrs; /* always add missing headers */ int var_virt_addrlen_limit; /* stop exponential growth */ char *var_hfrom_format; /* header_from_format */ +int var_force_mime_iconv; /* force mime downgrade on input */ int var_cleanup_mask_stray_cr_lf; /* replace stray CR or LF with space */ const CONFIG_INT_TABLE cleanup_int_table[] = { @@ -191,6 +192,7 @@ const CONFIG_BOOL_TABLE cleanup_bool_table[] = { VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off, VAR_AUTO_8BIT_ENC_HDR, DEF_AUTO_8BIT_ENC_HDR, &var_auto_8bit_enc_hdr, VAR_ALWAYS_ADD_HDRS, DEF_ALWAYS_ADD_HDRS, &var_always_add_hdrs, + VAR_FORCE_MIME_ICONV, DEF_FORCE_MIME_ICONV, &var_force_mime_iconv, VAR_CLEANUP_MASK_STRAY_CR_LF, DEF_CLEANUP_MASK_STRAY_CR_LF, &var_cleanup_mask_stray_cr_lf, 0, }; diff --git a/src/cleanup/cleanup_message.c b/src/cleanup/cleanup_message.c index 1ee0a52..0d31598 100644 --- a/src/cleanup/cleanup_message.c +++ b/src/cleanup/cleanup_message.c @@ -1069,6 +1069,9 @@ void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t */ mime_options = 0; if (var_disable_mime_input) { + if (var_force_mime_iconv) + msg_fatal("do not specify both %s=yes and %s=yes", + VAR_DISABLE_MIME_INPUT, VAR_FORCE_MIME_ICONV); mime_options |= MIME_OPT_DISABLE_MIME; } else { /* Turn off content checks if bouncing or forwarding mail. */ @@ -1085,6 +1088,8 @@ void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t || *var_nesthdr_checks) mime_options |= MIME_OPT_REPORT_NESTING; } + if (var_force_mime_iconv) + mime_options |= MIME_OPT_DOWNGRADE; } state->mime_state = mime_state_alloc(mime_options, cleanup_header_callback, diff --git a/src/cleanup/cleanup_milter.c b/src/cleanup/cleanup_milter.c index 491de25..a35344c 100644 --- a/src/cleanup/cleanup_milter.c +++ b/src/cleanup/cleanup_milter.c @@ -2444,6 +2444,7 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path) long data_offset; long rcpt_count; long qmgr_opts; + const HEADER_OPTS *opts; if (state->dst != 0) { msg_warn("closing %s", cleanup_path); @@ -2455,6 +2456,7 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path) if ((state->dst = vstream_fopen(path, O_RDWR, 0)) == 0) { msg_warn("open %s: %m", path); } else { + var_drop_hdrs = ""; cleanup_path = mystrdup(path); for (;;) { if ((curr_offset = vstream_ftell(state->dst)) < 0) @@ -2511,9 +2513,16 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path) msg_fatal("file %s: vstream_ftell: %m", cleanup_path); } } + } else if (rec_type == REC_TYPE_NORM && state->hop_count == 0 + && (opts = header_opts_find(STR(buf))) != 0 + && opts->type == HDR_RECEIVED) { + state->hop_count += 1; + /* XXX Only the first line of the first Received: header. */ + argv_add(state->auto_hdrs, STR(buf), ARGV_END); } if (state->append_rcpt_pt_offset > 0 && state->append_hdr_pt_offset > 0 + && state->hop_count > 0 && (rec_type == REC_TYPE_END || state->append_meta_pt_offset > 0)) break; diff --git a/src/cleanup/cleanup_milter.in18a b/src/cleanup/cleanup_milter.in18a new file mode 100644 index 0000000..4e60fe4 --- /dev/null +++ b/src/cleanup/cleanup_milter.in18a @@ -0,0 +1,8 @@ +#verbose on +open test-queue-file18a.tmp +# +# Update a prepended header. +# +upd_header 1 Header-Label new-header-value + +close diff --git a/src/cleanup/cleanup_milter.in18b b/src/cleanup/cleanup_milter.in18b new file mode 100644 index 0000000..5f8c12d --- /dev/null +++ b/src/cleanup/cleanup_milter.in18b @@ -0,0 +1,8 @@ +#verbose on +open test-queue-file18b.tmp +# +# Delete a prepended header. +# +del_header 1 Header-Label + +close diff --git a/src/cleanup/cleanup_milter.in18c b/src/cleanup/cleanup_milter.in18c new file mode 100644 index 0000000..bb78c94 --- /dev/null +++ b/src/cleanup/cleanup_milter.in18c @@ -0,0 +1,9 @@ +#verbose on +open test-queue-file18c.tmp +# +# Update the first Received: header. This adds a new header, because +# there is no header that was exposed to the Milter. +# +upd_header 1 Received whatever + +close diff --git a/src/cleanup/cleanup_milter.in18d b/src/cleanup/cleanup_milter.in18d new file mode 100644 index 0000000..607014d --- /dev/null +++ b/src/cleanup/cleanup_milter.in18d @@ -0,0 +1,8 @@ +#verbose on +open test-queue-file18d.tmp +# +# Delete our Received: header. This should do nothing. +# +del_header 1 Received + +close diff --git a/src/cleanup/cleanup_milter.ref18a1 b/src/cleanup/cleanup_milter.ref18a1 new file mode 100644 index 0000000..eab5a83 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18a1 @@ -0,0 +1 @@ +./cleanup_milter: flags = enable_header_body_filter enable_milters diff --git a/src/cleanup/cleanup_milter.ref18a2 b/src/cleanup/cleanup_milter.ref18a2 new file mode 100644 index 0000000..b5c0477 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18a2 @@ -0,0 +1,29 @@ +*** ENVELOPE RECORDS test-queue-file18a.tmp *** + 0 message_size: 342 290 1 0 342 0 + 97 message_arrival_time: Tue Dec 12 14:29:04 2023 + 116 create_time: Tue Dec 12 14:29:04 2023 + 140 named_attribute: rewrite_context=local + 163 sender_fullname: Wietse Venema + 178 sender: user@example.com + 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com + 235 original_recipient: user@example.com + 253 recipient: user@example.com + 271 pointer_record: 0 + 288 *** MESSAGE CONTENTS test-queue-file18a.tmp *** + 290 pointer_record: 653 + 653 regular_text: Header-Label: new-header-value + 685 pointer_record: 318 + 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000) + 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 438 regular_text: Subject: test + 453 padding: 0 + 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org> + 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 550 regular_text: From: Wietse Venema + 590 pointer_record: 0 + 607 regular_text: + 609 regular_text: test + 615 pointer_record: 0 + 632 *** HEADER EXTRACTED test-queue-file18a.tmp *** + 634 pointer_record: 0 + 651 *** MESSAGE FILE END test-queue-file18a.tmp *** diff --git a/src/cleanup/cleanup_milter.ref18b1 b/src/cleanup/cleanup_milter.ref18b1 new file mode 100644 index 0000000..eab5a83 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18b1 @@ -0,0 +1 @@ +./cleanup_milter: flags = enable_header_body_filter enable_milters diff --git a/src/cleanup/cleanup_milter.ref18b2 b/src/cleanup/cleanup_milter.ref18b2 new file mode 100644 index 0000000..d3b4ed3 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18b2 @@ -0,0 +1,27 @@ +*** ENVELOPE RECORDS test-queue-file18b.tmp *** + 0 message_size: 342 290 1 0 342 0 + 97 message_arrival_time: Tue Dec 12 14:29:04 2023 + 116 create_time: Tue Dec 12 14:29:04 2023 + 140 named_attribute: rewrite_context=local + 163 sender_fullname: Wietse Venema + 178 sender: user@example.com + 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com + 235 original_recipient: user@example.com + 253 recipient: user@example.com + 271 pointer_record: 0 + 288 *** MESSAGE CONTENTS test-queue-file18b.tmp *** + 290 pointer_record: 318 + 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000) + 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 438 regular_text: Subject: test + 453 padding: 0 + 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org> + 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 550 regular_text: From: Wietse Venema + 590 pointer_record: 0 + 607 regular_text: + 609 regular_text: test + 615 pointer_record: 0 + 632 *** HEADER EXTRACTED test-queue-file18b.tmp *** + 634 pointer_record: 0 + 651 *** MESSAGE FILE END test-queue-file18b.tmp *** diff --git a/src/cleanup/cleanup_milter.ref18c1 b/src/cleanup/cleanup_milter.ref18c1 new file mode 100644 index 0000000..eab5a83 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18c1 @@ -0,0 +1 @@ +./cleanup_milter: flags = enable_header_body_filter enable_milters diff --git a/src/cleanup/cleanup_milter.ref18c2 b/src/cleanup/cleanup_milter.ref18c2 new file mode 100644 index 0000000..84a3449 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18c2 @@ -0,0 +1,29 @@ +*** ENVELOPE RECORDS test-queue-file18c.tmp *** + 0 message_size: 342 290 1 0 342 0 + 97 message_arrival_time: Tue Dec 12 14:29:04 2023 + 116 create_time: Tue Dec 12 14:29:04 2023 + 140 named_attribute: rewrite_context=local + 163 sender_fullname: Wietse Venema + 178 sender: user@example.com + 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com + 235 original_recipient: user@example.com + 253 recipient: user@example.com + 271 pointer_record: 0 + 288 *** MESSAGE CONTENTS test-queue-file18c.tmp *** + 290 regular_text: Header-Label: header-value + 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000) + 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 438 regular_text: Subject: test + 453 padding: 0 + 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org> + 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 550 regular_text: From: Wietse Venema + 590 pointer_record: 653 + 653 regular_text: Received: whatever + 673 pointer_record: 607 + 607 regular_text: + 609 regular_text: test + 615 pointer_record: 0 + 632 *** HEADER EXTRACTED test-queue-file18c.tmp *** + 634 pointer_record: 0 + 651 *** MESSAGE FILE END test-queue-file18c.tmp *** diff --git a/src/cleanup/cleanup_milter.ref18d1 b/src/cleanup/cleanup_milter.ref18d1 new file mode 100644 index 0000000..eab5a83 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18d1 @@ -0,0 +1 @@ +./cleanup_milter: flags = enable_header_body_filter enable_milters diff --git a/src/cleanup/cleanup_milter.ref18d2 b/src/cleanup/cleanup_milter.ref18d2 new file mode 100644 index 0000000..b436ba2 --- /dev/null +++ b/src/cleanup/cleanup_milter.ref18d2 @@ -0,0 +1,27 @@ +*** ENVELOPE RECORDS test-queue-file18d.tmp *** + 0 message_size: 342 290 1 0 342 0 + 97 message_arrival_time: Tue Dec 12 14:29:04 2023 + 116 create_time: Tue Dec 12 14:29:04 2023 + 140 named_attribute: rewrite_context=local + 163 sender_fullname: Wietse Venema + 178 sender: user@example.com + 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com + 235 original_recipient: user@example.com + 253 recipient: user@example.com + 271 pointer_record: 0 + 288 *** MESSAGE CONTENTS test-queue-file18d.tmp *** + 290 regular_text: Header-Label: header-value + 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000) + 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 438 regular_text: Subject: test + 453 padding: 0 + 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org> + 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST) + 550 regular_text: From: Wietse Venema + 590 pointer_record: 0 + 607 regular_text: + 609 regular_text: test + 615 pointer_record: 0 + 632 *** HEADER EXTRACTED test-queue-file18d.tmp *** + 634 pointer_record: 0 + 651 *** MESSAGE FILE END test-queue-file18d.tmp *** diff --git a/src/cleanup/test-queue-file18 b/src/cleanup/test-queue-file18 new file mode 100644 index 0000000..42c46f1 Binary files /dev/null and b/src/cleanup/test-queue-file18 differ diff --git a/src/dns/Makefile.in b/src/dns/Makefile.in index 3ebf75f..5ea09cf 100644 --- a/src/dns/Makefile.in +++ b/src/dns/Makefile.in @@ -11,7 +11,8 @@ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) INCL = LIB = lib$(LIB_PREFIX)dns$(LIB_SUFFIX) -TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa +TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa \ + dns_rr_test LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \ ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX) LIB_DIR = ../../lib @@ -31,7 +32,7 @@ test: $(TESTPROG) tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \ dns_rr_eq_sa_test no-a-test no-aaaa-test no-mx-test \ error-filter-test nullmx_test nxdomain_test mxonly_test \ - dnsbl_tests + dnsbl_tests dns_rr_tests dnsbl_tests: \ dnsbl_ttl_127.0.0.2_bind_plain_test \ @@ -57,7 +58,7 @@ DNSBL_EXIST_REPLY_FIX = \ -e 's/ [0-9]* [0-9]* [0-9]* [0-9]* [0-9]*/ D D D D D/' \ -e 's/127.0.0.[0-9]*$$/127.0.0.D/' \ | uniq - + root_tests: $(LIB): $(OBJS) @@ -240,6 +241,12 @@ dnsbl_ttl_127.0.0.2_priv_ncache_test: test_dns_lookup dnsbl_ttl_127.0.0.2_bind_p diff dnsbl_ttl_127.0.0.2_bind_plain.ref dnsbl_ttl_127.0.0.2_priv_ncache.tmp rm -f dnsbl_ttl_127.0.0.2_priv_ncache.tmp +dns_rr_tests: dns_rr_test + $(SHLIB_ENV) $(VALGRIND) ./dns_rr_test + +dns_rr_test: dns_rr_test.o $(LIB) $(LIBS) + $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) + printfck: $(OBJS) $(PROG) rm -rf printfck mkdir printfck @@ -319,6 +326,19 @@ dns_rr_filter.o: ../../include/vstream.h dns_rr_filter.o: ../../include/vstring.h dns_rr_filter.o: dns.h dns_rr_filter.o: dns_rr_filter.c +dns_rr_test.o: ../../include/check_arg.h +dns_rr_test.o: ../../include/msg.h +dns_rr_test.o: ../../include/msg_vstream.h +dns_rr_test.o: ../../include/myaddrinfo.h +dns_rr_test.o: ../../include/mymalloc.h +dns_rr_test.o: ../../include/sock_addr.h +dns_rr_test.o: ../../include/stringops.h +dns_rr_test.o: ../../include/sys_defs.h +dns_rr_test.o: ../../include/vbuf.h +dns_rr_test.o: ../../include/vstream.h +dns_rr_test.o: ../../include/vstring.h +dns_rr_test.o: dns.h +dns_rr_test.o: dns_rr_test.c dns_rr_to_pa.o: ../../include/check_arg.h dns_rr_to_pa.o: ../../include/msg.h dns_rr_to_pa.o: ../../include/myaddrinfo.h diff --git a/src/dns/dns_lookup.c b/src/dns/dns_lookup.c index c21b619..4cf9a5f 100644 --- a/src/dns/dns_lookup.c +++ b/src/dns/dns_lookup.c @@ -85,6 +85,12 @@ /* an invalid name is reported as a DNS_INVAL result, while /* malformed replies are reported as transient errors. /* +/* Note: in dns_lookup*() results and queries, a name may start +/* with a "*" label, which is valid according to RFC 1034 +/* section 4.3.3. Such a name will not pass valid_hostname() +/* checks in the rest of Postfix, because it is not a valid +/* host or domain name. +/* /* dns_get_h_errno() returns the last error. This deprecates /* usage of the global h_errno variable. We should not rely /* on that being updated. @@ -300,7 +306,7 @@ typedef struct DNS_REPLY { /* * Use the threadsafe resolver API if available, not because it is - * theadsafe, but because it has more functionality. + * threadsafe, but because it has more functionality. */ #ifdef USE_RES_NCALLS static struct __res_state dns_res_state; diff --git a/src/dns/dns_rr_test.c b/src/dns/dns_rr_test.c new file mode 100644 index 0000000..7bbe769 --- /dev/null +++ b/src/dns/dns_rr_test.c @@ -0,0 +1,433 @@ + /* + * System library. + */ +#include +#include + + /* + * Utility library. + */ +#include +#include +#include +#include +#include + + /* + * DNS library. + */ +#include + +#define STR(x) vstring_str(x) + + /* + * Test helpers. TODO: move eq_dns_rr() to testing/dns_rr_testers.c; need to + * verify that the expected difference is reported, or use a GTEST matcher. + */ + +/* print_dns_rr - format as { qname, reply, flags } */ + +static char *print_dns_rr(VSTRING *buf, DNS_RR *rr) +{ + static VSTRING *tmp; + + if (tmp == 0) + tmp = vstring_alloc(100); + vstring_sprintf(buf, "{qname=%s, reply='%s', flags=0x%x}", + rr->qname, dns_strrecord(tmp, rr), rr->flags); + return (STR(buf)); +} + +/* eq_dns_rr - predicate that two lists are equivalent */ + +static int eq_dns_rr(DNS_RR *got, DNS_RR *want) +{ + VSTRING *got_buf = 0; + VSTRING *want_buf = 0; + +#define EQ_DNS_RR_RETURN(val) do { \ + if (got_buf) \ + vstring_free(got_buf); \ + if (want_buf) \ + vstring_free(want_buf); \ + return (val); \ + } while (0) + + /* Same length. */ + if (got == 0 && want == 0) + EQ_DNS_RR_RETURN(1); + if (want == 0) { + msg_warn("got %s, want null", + print_dns_rr(got_buf = vstring_alloc(100), got)); + } + if (got == 0) { + msg_warn("got null, want %s", + print_dns_rr(want_buf = vstring_alloc(100), want)); + EQ_DNS_RR_RETURN(0); + } + /* Same query name, resource record, flags. */ + if (strcmp(print_dns_rr(got_buf = vstring_alloc(100), got), + print_dns_rr(want_buf = vstring_alloc(100), want)) != 0) { + msg_warn("got %s, want %s", STR(want_buf), STR(got_buf)); + EQ_DNS_RR_RETURN(0); + } + /* Same children. */ + EQ_DNS_RR_RETURN(eq_dns_rr(got->next, want->next)); +} + +static int eq_dns_rr_free(DNS_RR *got, DNS_RR *want) +{ + int res = eq_dns_rr(got, want); + + dns_rr_free(got); + dns_rr_free(want); + return (res); +} + + /* + * Tests and test cases. + */ +typedef struct TEST_CASE { + const char *label; /* identifies test case */ + int (*fn) (void); +} TEST_CASE; + +#define PASS (0) +#define FAIL (1) + + /* + * Begin helper tests. TODO: move these to testing/dns_rr_testers_test.c. + */ + +static int eq_dns_rr_qname_differ(void) +{ + DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 4); + DNS_RR *want = dns_rr_copy(got); + + myfree(want->qname); + want->qname = mystrdup("qb"); + return (!eq_dns_rr_free(got, want)); +} + +static int eq_dns_rr_reply_differ(void) +{ + DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 4); + DNS_RR *want = dns_rr_copy(got); + + want->port += 1; + return (!eq_dns_rr_free(got, want)); +} + + /* + * End helper tests. + */ + + /* + * Begin DNS_RR tests. + */ + +static int eq_dns_rr_flags_differ(void) +{ + DNS_RR *got = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *want = dns_rr_copy(got); + + want->flags |= DNS_RR_FLAG_TRUNCATED; + return (!eq_dns_rr_free(got, want)); +} + +static int append_to_null_from_null(void) +{ + DNS_RR *got = dns_rr_append((DNS_RR *) 0, (DNS_RR *) 0); + DNS_RR *want = 0; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_null(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_copy(a), (DNS_RR *) 0); + + want = a; + + return (eq_dns_rr_free(got, want)); +} + +static int appent_to_null_from_elem(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *got, *want; + + got = dns_rr_append((DNS_RR *) 0, dns_rr_copy(a)); + + want = a; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_elem(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b)); + + (want = a)->next = b; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_list(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_copy(a), + dns_rr_append(dns_rr_copy(b), + dns_rr_copy(c))); + + ((want = a)->next = b)->next = c; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_append(dns_rr_copy(a), + dns_rr_copy(b)), + dns_rr_copy(c)); + + ((want = a)->next = b)->next = c; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_list(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *got, *want; + + got = dns_rr_append(dns_rr_append(dns_rr_copy(a), + dns_rr_copy(b)), + dns_rr_append(dns_rr_copy(c), + dns_rr_copy(d))); + + (((want = a)->next = b)->next = c)->next = d; + + return (eq_dns_rr_free(got, want)); +} + +static int append_propagates_flags(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *left = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b)); + DNS_RR *rite = dns_rr_append(dns_rr_copy(c), dns_rr_copy(d)); + DNS_RR *got, *want, *rr; + + for (rr = rite; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(left, rite); + + (((want = a)->next = b)->next = c)->next = d; + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_list_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 3; + + ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(dns_rr_append(a, b), + dns_rr_append(c, d)); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem_elem_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 2; + + (want = dns_rr_copy(a))->next = dns_rr_copy(b); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(a, b); + got = dns_rr_append(got, c); /* should be logged */ + got = dns_rr_append(got, d); /* should be silent */ + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 2; + + (want = dns_rr_copy(a))->next = dns_rr_copy(b); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(dns_rr_append(a, b), c); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_list_truncate(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want, *rr; + + var_dns_rr_list_limit = 2; + + (want = dns_rr_copy(a))->next = dns_rr_copy(b); + for (rr = want; rr; rr = rr->next) + rr->flags |= DNS_RR_FLAG_TRUNCATED; + + got = dns_rr_append(a, dns_rr_append(b, c)); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_list_from_elem_exact_fit(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + var_dns_rr_list_limit = 3; + + ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c); + + got = dns_rr_append(dns_rr_append(a, b), c); + + return (eq_dns_rr_free(got, want)); +} + +static int append_to_elem_from_list_exact_fit(void) +{ + DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4); + DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4); + DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4); + DNS_RR *got, *want; + + var_dns_rr_list_limit = 3; + + ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c); + + got = dns_rr_append(a, dns_rr_append(b, c)); + + return (eq_dns_rr_free(got, want)); +} + + /* + * The test cases. + */ +static const TEST_CASE test_cases[] = { + + /* + * Test eq_dns_rr; TODO: move to testing/dns_rr_testers_test.c + */ + "eq_dns_rr qname differ", eq_dns_rr_qname_differ, + "eq_dns_rr reply differ", eq_dns_rr_reply_differ, + "eq_dns_rr flags differ", eq_dns_rr_flags_differ, + + /* + * Test dns_rr_append() without truncation. + */ + "append to null from null", append_to_null_from_null, + "append to null from element", appent_to_null_from_elem, + "append to element from null", append_to_elem_from_null, + "append to element from element", append_to_elem_from_elem, + "append to element from list", append_to_elem_from_list, + "append to list from element", append_to_list_from_elem, + "append to list from list", append_to_list_from_list, + + /* + * Test dns_rr_append() flag propagation. + */ + "append propagates flags", append_propagates_flags, + + /* + * Test dns_rr_append() with truncation. + */ + "append to list from list truncate", append_to_list_from_list_truncate, + "append to list from element element truncate", append_to_list_from_elem_elem_truncate, + "append to list from element truncate", append_to_list_from_elem_truncate, + "append to element from list truncate", append_to_elem_from_list_truncate, + "append to list from element exact fit", append_to_list_from_elem_exact_fit, + "append to element from list exact fit", append_to_elem_from_list_exact_fit, + + /* + * TODO: tests dns_rr_sort(), dns_rr_srv_sort(), dns_rr_remove(), + * dns_rr_shuffle(), etc. + */ + 0, +}; + +int main(int argc, char **argv) +{ + const TEST_CASE *tp; + int pass = 0; + int fail = 0; + VSTRING *res_buf = vstring_alloc(100); + int saved_limit = var_dns_rr_list_limit; + + msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR); + + for (tp = test_cases; tp->label != 0; tp++) { + msg_info("RUN %s", tp->label); + if (tp->fn() == 0) { + fail++; + msg_info("FAIL %s", tp->label); + } else { + msg_info("PASS %s", tp->label); + pass++; + } + var_dns_rr_list_limit = saved_limit; + } + msg_info("PASS=%d FAIL=%d", pass, fail); + vstring_free(res_buf); + exit(fail != 0); +} diff --git a/src/dns/mxonly_test.ref b/src/dns/mxonly_test.ref index 44f22d6..e1e4bad 100644 --- a/src/dns/mxonly_test.ref +++ b/src/dns/mxonly_test.ref @@ -6,6 +6,6 @@ ./test_dns_lookup: lookup porcupine.org type A flags RES_USE_DNSSEC ./test_dns_lookup: dns_query: porcupine.org (A): Host found but no data record of requested type ad: 0, rr: porcupine.org. 3600 IN MX 10 spike.porcupine.org. -ad: 0, rr: porcupine.org. 3600 IN MX 30 m1.porcupine.org. ad: 0, rr: porcupine.org. 3600 IN MX 30 vz.porcupine.org. +ad: 0, rr: porcupine.org. 3600 IN MX 40 m1.porcupine.org. porcupine.org: fqdn: porcupine.org diff --git a/src/dns/no-mx.ref b/src/dns/no-mx.ref index 5adc7bf..527e0b8 100644 --- a/src/dns/no-mx.ref +++ b/src/dns/no-mx.ref @@ -1,15 +1,15 @@ ./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 10 spike.porcupine.org. -./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 30 m1.porcupine.org. ./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 30 vz.porcupine.org. +./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 40 m1.porcupine.org. ./test_dns_lookup: dns_get_answer: type MX for porcupine.org ./test_dns_lookup: dns_get_answer: type MX for porcupine.org ./test_dns_lookup: dns_get_answer: type MX for porcupine.org ./test_dns_lookup: dns_query: porcupine.org (MX): OK ./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 10 spike.porcupine.org. -./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 30 m1.porcupine.org. ./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 30 vz.porcupine.org. +./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 40 m1.porcupine.org. ./test_dns_lookup: lookup porcupine.org type MX flags RES_USE_DNSSEC ./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 10 spike.porcupine.org. = ignore -./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 30 m1.porcupine.org. = ignore ./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 30 vz.porcupine.org. = ignore +./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 40 m1.porcupine.org. = ignore ./test_dns_lookup: warning: Error looking up name=porcupine.org type=MX: DNS reply filter drops all results (rcode=0) diff --git a/src/dns/test_dns_lookup.c b/src/dns/test_dns_lookup.c index f07c3ef..6970124 100644 --- a/src/dns/test_dns_lookup.c +++ b/src/dns/test_dns_lookup.c @@ -80,7 +80,7 @@ int main(int argc, char **argv) var_dnssec_probe = ""; msg_vstream_init(argv[0], VSTREAM_ERR); - while ((ch = GETOPT(argc, argv, "f:npvs")) > 0) { + while ((ch = GETOPT(argc, argv, "f:l:npvs")) > 0) { switch (ch) { case 'v': msg_verbose++; @@ -88,6 +88,9 @@ int main(int argc, char **argv) case 'f': dns_rr_filter_compile("DNS reply filter", optarg); break; + case 'l': + var_dns_rr_list_limit = atoi(optarg); + break; case 'n': lflags |= DNS_REQ_FLAG_NCACHE_TTL; break; diff --git a/src/dnsblog/dnsblog.c b/src/dnsblog/dnsblog.c index bc87c4b..7a4a446 100644 --- a/src/dnsblog/dnsblog.c +++ b/src/dnsblog/dnsblog.c @@ -43,7 +43,8 @@ /* How much time a Postfix daemon process may take to handle a /* request before it is terminated by a built-in watchdog timer. /* .IP "\fBpostscreen_dnsbl_sites (empty)\fR" -/* Optional list of DNS allow/denylist domains, filters and weight +/* Optional list of patterns with DNS allow/denylist domains, filters +/* and weight /* factors. /* .IP "\fBipc_timeout (3600s)\fR" /* The time limit for sending or receiving information over an internal diff --git a/src/global/Makefile.in b/src/global/Makefile.in index 86390ed..c7a1d36 100644 --- a/src/global/Makefile.in +++ b/src/global/Makefile.in @@ -3,7 +3,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ canon_addr.c cfg_parser.c cleanup_strerror.c cleanup_strflags.c \ clnt_stream.c conv_time.c db_common.c debug_peer.c debug_process.c \ defer.c deliver_completed.c deliver_flock.c deliver_pass.c \ - deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c \ + deliver_request.c dict_ldap.c dict_mongodb.c dict_mysql.c dict_pgsql.c \ dict_proxy.c dict_sqlite.c domain_list.c dot_lockfile.c dot_lockfile_as.c \ dsb_scan.c dsn.c dsn_buf.c dsn_mask.c dsn_print.c dsn_util.c \ ehlo_mask.c ext_prop.c file_id.c flush_clnt.c header_opts.c \ @@ -80,13 +80,13 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. -MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o +MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o dict_mongodb.o HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \ conv_time.h db_common.h debug_peer.h debug_process.h defer.h \ deliver_completed.h deliver_flock.h deliver_pass.h deliver_request.h \ - dict_ldap.h dict_mysql.h dict_pgsql.h dict_proxy.h dict_sqlite.h domain_list.h \ + dict_ldap.h dict_mysql.h dict_pgsql.h dict_mongodb.h dict_proxy.h dict_sqlite.h domain_list.h \ dot_lockfile.h dot_lockfile_as.h dsb_scan.h dsn.h dsn_buf.h \ dsn_mask.h dsn_print.h dsn_util.h ehlo_mask.h ext_prop.h \ file_id.h flush_clnt.h header_opts.h header_token.h input_transp.h \ @@ -136,7 +136,7 @@ LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX) LIB_DIR = ../../lib INC_DIR = ../../include PLUGIN_MAP_SO = $(LIB_PREFIX)ldap$(LIB_SUFFIX) $(LIB_PREFIX)mysql$(LIB_SUFFIX) \ - $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) + $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) $(LIB_PREFIX)mongodb$(LIB_SUFFIX) MAKES = .c.o:; $(CC) $(SHLIB_CFLAGS) $(CFLAGS) -c $*.c @@ -173,6 +173,9 @@ $(LIB_PREFIX)pgsql$(LIB_SUFFIX): dict_pgsql.o $(LIB_PREFIX)sqlite$(LIB_SUFFIX): dict_sqlite.o $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_sqlite.o $(AUXLIBS_SQLITE) +$(LIB_PREFIX)mongodb$(LIB_SUFFIX): dict_mongodb.o + $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_mongodb.o $(AUXLIBS_MONGODB) + update: $(LIB_DIR)/$(LIB) $(HDRS) $(PLUGIN_MAP_SO_UPDATE) -for i in $(HDRS); \ do \ @@ -1210,6 +1213,24 @@ dict_memcache.o: dict_memcache.c dict_memcache.o: dict_memcache.h dict_memcache.o: memcache_proto.h dict_memcache.o: string_list.h +dict_mongodb.o: ../../include/argv.h +dict_mongodb.o: ../../include/auto_clnt.h +dict_mongodb.o: ../../include/check_arg.h +dict_mongodb.o: ../../include/dict.h +dict_mongodb.o: ../../include/match_list.h +dict_mongodb.o: ../../include/msg.h +dict_mongodb.o: ../../include/myflock.h +dict_mongodb.o: ../../include/mymalloc.h +dict_mongodb.o: ../../include/stringops.h +dict_mongodb.o: ../../include/sys_defs.h +dict_mongodb.o: ../../include/vbuf.h +dict_mongodb.o: ../../include/vstream.h +dict_mongodb.o: ../../include/vstring.h +dict_mongodb.o: cfg_parser.h +dict_mongodb.o: db_common.h +dict_mongodb.o: dict_mongodb.c +dict_mongodb.o: dict_mongodb.h +dict_mongodb.o: string_list.h dict_mysql.o: ../../include/argv.h dict_mysql.o: ../../include/check_arg.h dict_mysql.o: ../../include/dict.h @@ -1861,6 +1882,7 @@ mail_dict.o: ../../include/vstream.h mail_dict.o: ../../include/vstring.h mail_dict.o: dict_ldap.h mail_dict.o: dict_memcache.h +mail_dict.o: dict_mongodb.h mail_dict.o: dict_mysql.h mail_dict.o: dict_pgsql.h mail_dict.o: dict_proxy.h @@ -1911,6 +1933,7 @@ mail_params.o: ../../include/htable.h mail_params.o: ../../include/inet_addr_list.h mail_params.o: ../../include/inet_proto.h mail_params.o: ../../include/iostuff.h +mail_params.o: ../../include/logwriter.h mail_params.o: ../../include/midna_domain.h mail_params.o: ../../include/mkmap.h mail_params.o: ../../include/msg.h diff --git a/src/global/dict_ldap.c b/src/global/dict_ldap.c index a078721..7310a96 100644 --- a/src/global/dict_ldap.c +++ b/src/global/dict_ldap.c @@ -904,7 +904,7 @@ static int attrdesc_subtype(const char *a1, const char *a2) /* url_attrs - attributes we want from LDAP URL */ -static char **url_attrs(DICT_LDAP *dict_ldap, LDAPURLDesc * url) +static char **url_attrs(DICT_LDAP *dict_ldap, LDAPURLDesc *url) { static ARGV *attrs; char **a1; @@ -1234,7 +1234,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) * Don't frustrate future attempts to make Postfix UTF-8 transparent. */ if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 - && !valid_utf8_string(name, strlen(name))) { + && !valid_utf8_stringz(name)) { if (msg_verbose) msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", myname, dict_ldap->parser->name, name); diff --git a/src/global/dict_mongodb.c b/src/global/dict_mongodb.c new file mode 100644 index 0000000..18144b7 --- /dev/null +++ b/src/global/dict_mongodb.c @@ -0,0 +1,570 @@ +/*++ +/* NAME +/* dict_mongodb 3 +/* SUMMARY +/* dictionary interface to mongodb, compatible with libmongoc-1.0 +/* SYNOPSIS +/* #include +/* +/* DICT *dict_mongodb_open(name, open_flags, dict_flags) +/* const char *name; +/* int open_flags; +/* int dict_flags; +/* DESCRIPTION +/* dict_mongodb_open() opens a MongoDB database, providing a +/* dictionary interface for Postfix mappings. The result is a +/* pointer to the installed dictionary. +/* +/* Configuration parameters are described in mongodb_table(5). +/* +/* Arguments: +/* .IP name +/* Either the path to the MongoDB configuration file (if it +/* starts with '/' or '.'), or the prefix which will be used +/* to obtain main.cf configuration parameters for this search. +/* +/* In the first case, configuration parameters are specified +/* in the file as \fIname\fR=\fIvalue\fR pairs. +/* +/* In the second case, the configuration parameters are prefixed +/* with the value of \fIname\fR and an underscore, and they +/* are specified in main.cf. For example, if this value is +/* \fImongodbconf\fR, the parameters would look like +/* \fImongodbconf_uri\fR, \fImongodbconf_collection\fR, and +/* so on. +/* .IP open_flags +/* Must be O_RDONLY +/* .IP dict_flags +/* See dict_open(3). +/* SEE ALSO +/* dict(3) generic dictionary manager +/* HISTORY +/* .ad +/* .fi +/* MongoDB support was added in Postfix 3.9. +/* AUTHOR(S) +/* Hamid Maadani (hamid@dexo.tech) +/* Dextrous Technologies, LLC +/* +/* Edited by: +/* Wietse Venema +/* porcupine.org +/* +/* Based on prior work by: +/* Stephan Ferraro +/* Aionda GmbH +/*--*/ + + /* + * System library. + */ +#include +#ifdef HAS_MONGODB +#include +#include +#include +#include +#include +#include /* C99 PRId64 */ + +#include +#include + + /* + * Utility library. + */ +#include +#include +#include +#include +#include +#include +#include + + /* + * Global library. + */ +#include +#include + + /* + * Application-specific. + */ +#include + + /* + * Initial size for dynamically-allocated buffers. + */ +#ifndef BUFFER_SIZE +#define BUFFER_SIZE 1024 +#endif + +#define INIT_VSTR(buf, len) do { \ + if (buf == 0) \ + buf = vstring_alloc(len); \ + VSTRING_RESET(buf); \ + VSTRING_TERMINATE(buf); \ + } while (0) + +/* Structure of one mongodb dictionary handle. */ +typedef struct { + /* Initialized by dict_mongodb_open(). */ + DICT dict; /* Parent class */ + CFG_PARSER *parser; /* Configuration file parser */ + mongoc_client_t *client; /* Mongo C client handle */ + /* Initialized by mongodb_parse_config(). */ + char *uri; /* mongodb+srv:/*localhost:27017 */ + char *dbname; /* Database name */ + char *collection; /* Collection name */ + char *query_filter; /* db_common_expand() query template */ + char *projection; /* Advanced MongoDB projection */ + char *result_attribute; /* The key(s) to return the data for */ + char *result_format; /* db_common_expand() result_template */ + int expansion_limit; /* Result expansion limit */ + void *ctx; /* db_common handle */ +} DICT_MONGODB; + +/* Per-process initialization. */ +static bool init_done = false; + +/* itoa - int64_t to string */ + +static char *itoa(int64_t val) +{ + static char buf[21] = {0}; + int ret; + + /* + * XXX(Wietse) replaced custom code with standard library calls that + * handle zero, and negative values. + */ +#define PRId64_FORMAT "%" PRId64 + + ret = snprintf(buf, sizeof(buf), PRId64_FORMAT, val); + if (ret < 0) + msg_panic("itoa: output error for '%s'", PRId64_FORMAT); + if (ret >= sizeof(buf)) + msg_panic("itoa: output for '%s' exceeds space %ld", + PRId64_FORMAT, sizeof(buf)); + return (buf); +} + +/* mongodb_parse_config - parse mongodb configuration file */ + +static void mongodb_parse_config(DICT_MONGODB *dict_mongodb, + const char *mongodbcf) +{ + CFG_PARSER *p = dict_mongodb->parser; + + /* + * Parse the configuration file. + */ + dict_mongodb->uri = cfg_get_str(p, "uri", NULL, 1, 0); + dict_mongodb->dbname = cfg_get_str(p, "dbname", NULL, 1, 0); + dict_mongodb->collection = cfg_get_str(p, "collection", NULL, 1, 0); + dict_mongodb->query_filter = cfg_get_str(p, "query_filter", NULL, 1, 0); + + /* + * One of projection and result_attribute must be specified. That is + * enforced in the caller. + */ + dict_mongodb->projection = cfg_get_str(p, "projection", NULL, 0, 0); + dict_mongodb->result_attribute + = cfg_get_str(p, "result_attribute", NULL, 0, 0); + dict_mongodb->result_format + = cfg_get_str(dict_mongodb->parser, "result_format", "%s", 1, 0); + dict_mongodb->expansion_limit + = cfg_get_int(dict_mongodb->parser, "expansion_limit", 10, 0, 100); + + /* + * db_common query parsing and domain pattern lookup. + */ + dict_mongodb->ctx = 0; + (void) db_common_parse(&dict_mongodb->dict, &dict_mongodb->ctx, + dict_mongodb->query_filter, 1); + db_common_parse_domain(dict_mongodb->parser, dict_mongodb->ctx); +} + +/* expand_value - expand lookup result value */ + +static bool expand_value(DICT_MONGODB *dict_mongodb, const char *p, + const char *lookup_name, + VSTRING *resultString, + int *expansion, const char *key) +{ + + /* + * If a lookup result cannot be processed due to an expansion limit + * error, return a DICT_ERR_RETRY error code and a 'false' result value. + * As documented for many dict_xxx() implementations, and expansion limit + * error is considered a temporary error. + */ + if (dict_mongodb->expansion_limit > 0 + && ++(*expansion) > dict_mongodb->expansion_limit) { + msg_warn("%s:%s: expansion limit exceeded for key: '%s'", + dict_mongodb->dict.type, dict_mongodb->dict.name, key); + dict_mongodb->dict.error = DICT_ERR_RETRY; + return (false); + } + + /* + * XXX(Wietse) Added the dict_mongodb_lookup() lookup_name argument, + * because it selects code paths inside db_common_expand() that are + * specifically for lookup results instead of lookup keys, including + * %[SUD] substitution. + */ + db_common_expand(dict_mongodb->ctx, dict_mongodb->result_format, p, + lookup_name, resultString, 0); + return (true); +} + +/* get_result_string - convert lookup result to string, or set dict.error */ + +static char *get_result_string(DICT_MONGODB *dict_mongodb, + VSTRING *resultString, + bson_iter_t *iter, + const char *lookup_name, + int *expansion, + const char *key) +{ + char *p = NULL; + bool got_one_result = false; + + /* + * If a lookup result cannot be processed due to an error, return a + * non-zero error code and a NULL result value. + */ + INIT_VSTR(resultString, BUFFER_SIZE); + while (dict_mongodb->dict.error == DICT_ERR_NONE && bson_iter_next(iter)) { + switch (bson_iter_type(iter)) { + case BSON_TYPE_UTF8: + p = (char *) bson_iter_utf8(iter, NULL); + if (!bson_utf8_validate(p, strlen(p), true)) { + msg_warn("%s:%s: invalid UTF-8 in lookup result '%s'", + dict_mongodb->dict.type, dict_mongodb->dict.name, p); + dict_mongodb->dict.error = DICT_ERR_RETRY; + break; + } + got_one_result |= expand_value(dict_mongodb, p, lookup_name, + resultString, expansion, key); + break; + case BSON_TYPE_INT64: + case BSON_TYPE_INT32: + p = itoa(bson_iter_as_int64(iter)); + got_one_result |= expand_value(dict_mongodb, p, lookup_name, + resultString, expansion, key); + break; + case BSON_TYPE_ARRAY: + ; /* For pre-C23 Clang. */ + const uint8_t *dataBuffer = NULL; + unsigned int len = 0; + bson_iter_t dataIter; + bson_t *data = NULL; + + /* + * XXX(Wietse) are there any non-error cases, such as a valid but + * empty array, where bson_new_from_data() or bson_iter_init() + * would return null or false? If there are no such cases then we + * must handle null/false as an error. + */ + bson_iter_array(iter, &len, &dataBuffer); + if ((data = bson_new_from_data(dataBuffer, len)) != 0 + && bson_iter_init(&dataIter, data)) { + VSTRING *iterResult = vstring_alloc(BUFFER_SIZE); + + if ((p = get_result_string(dict_mongodb, iterResult, &dataIter, + lookup_name, expansion, key)) != 0) { + vstring_sprintf_append(resultString, (got_one_result) ? + ",%s" : "%s", p); + got_one_result |= true; + } + vstring_free(iterResult); + } + bson_destroy(data); + break; + default: + /* Unexpected field type. As documented, warn and ignore. */ + msg_warn("%s:%s: failed to retrieve value of '%s', " + "Unknown result type %d.", dict_mongodb->dict.type, + dict_mongodb->dict.name, bson_iter_key(iter), + bson_iter_type(iter)); + break; + } + } + if (dict_mongodb->dict.error != DICT_ERR_NONE || !got_one_result) + return (0); + return (vstring_str(resultString)); +} + +/* dict_mongdb_quote - quote json string */ + +static void dict_mongdb_quote(DICT *dict, const char *name, VSTRING *result) +{ + /* quote_for_json_append() will resize the result buffer as needed. */ + (void) quote_for_json_append(result, name, -1); +} + +/* dict_mongdb_append_result_attributes - projection builder */ + +static int dict_mongdb_append_result_attribute(bson_t * projection, + const char *result_attribute) +{ + char *ra = mystrdup(result_attribute); + char *pp = ra; + char *cp; + int ok = 1; + + while (ok && (cp = mystrtok(&pp, CHARS_COMMA_SP)) != 0) + ok = BSON_APPEND_INT32(projection, cp, 1); + myfree(ra); + return (ok); +} + +/* dict_mongodb_lookup - find database entry using mongo query language */ + +static const char *dict_mongodb_lookup(DICT *dict, const char *name) +{ + DICT_MONGODB *dict_mongodb = (DICT_MONGODB *) dict; + mongoc_collection_t *coll = NULL; + mongoc_cursor_t *cursor = NULL; + bson_iter_t iter; + const bson_t *doc = NULL; + bson_t *query = NULL; + bson_t *options = NULL; + bson_t *projection = NULL; + bson_error_t error; + char *result = NULL; + static VSTRING *queryString = NULL; + static VSTRING *resultString = NULL; + int domain_rc; + int expansion = 0; + + dict_mongodb->dict.error = DICT_ERR_NONE; + + /* + * If they specified a domain list for this map, then only search for + * addresses in domains on the list. This can significantly reduce the + * load on the database. + */ + if ((domain_rc = db_common_check_domain(dict_mongodb->ctx, name)) == 0) { + if (msg_verbose) + msg_info("%s:%s: skipping lookup of '%s': domain mismatch", + dict_mongodb->dict.type, dict_mongodb->dict.name, name); + return (0); + } else if (domain_rc < 0) { + DICT_ERR_VAL_RETURN(dict, domain_rc, (char *) 0); + } + + /* + * Ugly macros to make error and non-error handling code more readable. + * If code size is a concern, them an optimizing compiler can eliminate + * dead code or duplicated code. + */ + + /* Set an error code, and return null. */ +#define DICT_MONGODB_LOOKUP_ERR_RETURN(err) do { \ + dict_mongodb->dict.error = (err); \ + DICT_MONGODB_LOOKUP_RETURN((char *) 0); \ +} while (0); + + /* Pass through any error, and return the specified value. */ +#define DICT_MONGODB_LOOKUP_RETURN(val) do { \ + if (coll) mongoc_collection_destroy(coll); \ + if (cursor) mongoc_cursor_destroy(cursor); \ + if (query) bson_destroy(query); \ + if (options) bson_destroy(options); \ + if (projection) bson_destroy(projection); \ + return (val); \ + } while (0) + + coll = mongoc_client_get_collection(dict_mongodb->client, + dict_mongodb->dbname, + dict_mongodb->collection); + if (!coll) { + msg_warn("%s:%s: failed to get collection [%s] from [%s]", + dict_mongodb->dict.type, dict_mongodb->dict.name, + dict_mongodb->collection, dict_mongodb->dbname); + DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY); + } + + /* + * Use the specified result projection, or craft one from the + * result_attribute. Exclude the _id field from the result. + */ + options = bson_new(); + if (dict_mongodb->projection) { + projection = bson_new_from_json((uint8_t *) dict_mongodb->projection, + -1, &error); + if (!projection) { + msg_warn("%s:%s: failed to create a projection from '%s': %s", + dict_mongodb->dict.type, dict_mongodb->dict.name, + dict_mongodb->projection, error.message); + DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY); + } + if (!BSON_APPEND_INT32(projection, "_id", 0) + || !BSON_APPEND_DOCUMENT(options, "projection", projection)) { + msg_warn("%s:%s: failed to append a projection from '%s'", + dict_mongodb->dict.type, dict_mongodb->dict.name, + dict_mongodb->projection); + DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY); + } + } else if (dict_mongodb->result_attribute) { + bson_t res_attr; + + if (!BSON_APPEND_DOCUMENT_BEGIN(options, "projection", &res_attr) + || !BSON_APPEND_INT32(&res_attr, "_id", 0) + || !dict_mongdb_append_result_attribute(&res_attr, + dict_mongodb->result_attribute) + || !bson_append_document_end(options, &res_attr)) { + msg_warn("%s:%s: failed to append a projection from '%s'", + dict_mongodb->dict.type, dict_mongodb->dict.name, + dict_mongodb->result_attribute); + DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY); + } + } else { + /* Can't happen. The configuration parser should reject this. */ + msg_panic("%s:%s: empty 'projection' and 'result_attribute'", + dict_mongodb->dict.type, dict_mongodb->dict.name); + } + + /* + * Expand filter template. This uses a quoting function to prevent + * metacharacter injection with parts from a crafted email address. + */ + INIT_VSTR(queryString, BUFFER_SIZE); + if (!db_common_expand(dict_mongodb->ctx, dict_mongodb->query_filter, + name, 0, queryString, dict_mongdb_quote)) + /* Suppress the actual lookup if the expansion is empty. */ + DICT_MONGODB_LOOKUP_RETURN(0); + + /* Create the query from the expanded query template. */ + query = bson_new_from_json((uint8_t *) vstring_str(queryString), + -1, &error); + if (!query) { + msg_warn("%s:%s: failed to create a query from '%s': %s", + dict_mongodb->dict.type, dict_mongodb->dict.name, + vstring_str(queryString), error.message); + DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY); + } + /* Run the query. */ + cursor = mongoc_collection_find_with_opts(coll, query, options, NULL); + if (mongoc_cursor_error(cursor, &error)) { + msg_warn("%s:%s: cursor error for '%s': %s", + dict_mongodb->dict.type, dict_mongodb->dict.name, + vstring_str(queryString), error.message); + DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY); + } + /* Convert the lookup result to C string. */ + INIT_VSTR(resultString, BUFFER_SIZE); + while (mongoc_cursor_next(cursor, &doc)) { + if (bson_iter_init(&iter, doc)) { + result = get_result_string(dict_mongodb, resultString, &iter, + name, &expansion, name); + } + } + DICT_MONGODB_LOOKUP_RETURN(result); +} + +/* dict_mongodb_close - close MongoDB database */ + +static void dict_mongodb_close(DICT *dict) +{ + DICT_MONGODB *dict_mongodb = (DICT_MONGODB *) dict; + + cfg_parser_free(dict_mongodb->parser); + if (dict_mongodb->ctx) { + db_common_free_ctx(dict_mongodb->ctx); + } + myfree(dict_mongodb->uri); + myfree(dict_mongodb->dbname); + myfree(dict_mongodb->collection); + myfree(dict_mongodb->query_filter); + + if (dict_mongodb->result_attribute) { + myfree(dict_mongodb->result_attribute); + } + if (dict_mongodb->result_format) { + myfree(dict_mongodb->result_format); + } + if (dict_mongodb->projection) { + myfree(dict_mongodb->projection); + } + if (dict_mongodb->client) { + mongoc_client_destroy(dict_mongodb->client); + } + dict_free(dict); +} + +/* dict_mongodb_open - open MongoDB database connection */ + +DICT *dict_mongodb_open(const char *name, int open_flags, int dict_flags) +{ + DICT_MONGODB *dict_mongodb; + CFG_PARSER *parser; + mongoc_uri_t *uri = 0; + bson_error_t error; + + /* Sanity checks. */ + if (open_flags != O_RDONLY) { + return (dict_surrogate(DICT_TYPE_MONGODB, name, open_flags, dict_flags, + "%s:%s: map requires O_RDONLY access mode", + DICT_TYPE_MONGODB, name)); + } + /* Open the configuration file. */ + if ((parser = cfg_parser_alloc(name)) == 0) { + return (dict_surrogate(DICT_TYPE_MONGODB, name, open_flags, dict_flags, + "open %s: %m", name)); + } + /* Create the dictionary object. */ + dict_mongodb = (DICT_MONGODB *) dict_alloc(DICT_TYPE_MONGODB, name, + sizeof(*dict_mongodb)); + dict_mongodb->dict.lookup = dict_mongodb_lookup; + dict_mongodb->dict.close = dict_mongodb_close; + dict_mongodb->dict.flags = dict_flags; + dict_mongodb->parser = parser; + dict_mongodb->dict.owner = cfg_get_owner(dict_mongodb->parser); + dict_mongodb->client = NULL; + + /* Parse config. */ + mongodb_parse_config(dict_mongodb, name); + if (!dict_mongodb->projection == !dict_mongodb->result_attribute) { + dict_mongodb_close(&dict_mongodb->dict); + return (dict_surrogate(DICT_TYPE_MONGODB, name, open_flags, dict_flags, + "%s:%s: specify exactly one of 'projection' or 'result_attribute'", + DICT_TYPE_MONGODB, name)); + } + /* One-time initialization of libmongoc 's internals. */ + if (!init_done) { + mongoc_init(); + init_done = true; + } +#define DICT_MONGODB_OPEN_ERR_RETURN(d) do { \ + DICT *_d = (d); \ + if (uri) mongoc_uri_destroy(uri); \ + dict_mongodb_close(&dict_mongodb->dict); \ + return (_d); \ + } while (0); + + uri = mongoc_uri_new_with_error(dict_mongodb->uri, &error); + if (!uri) + DICT_MONGODB_OPEN_ERR_RETURN(dict_surrogate(DICT_TYPE_MONGODB, name, + open_flags, dict_flags, + "%s:%s: failed to parse URI '%s': %s", + DICT_TYPE_MONGODB, name, + dict_mongodb->uri, error.message)); + + dict_mongodb->client = mongoc_client_new_from_uri_with_error(uri, &error); + if (!dict_mongodb->client) + DICT_MONGODB_OPEN_ERR_RETURN(dict_surrogate(DICT_TYPE_MONGODB, name, + open_flags, dict_flags, + "%s:%s: failed to create client for '%s': %s", + DICT_TYPE_MONGODB, name, + dict_mongodb->uri, + error.message)); + + mongoc_uri_destroy(uri); + mongoc_client_set_error_api(dict_mongodb->client, MONGOC_ERROR_API_VERSION_2); + return (DICT_DEBUG (&dict_mongodb->dict)); +} + +#endif diff --git a/src/global/dict_mongodb.h b/src/global/dict_mongodb.h new file mode 100755 index 0000000..d5120cb --- /dev/null +++ b/src/global/dict_mongodb.h @@ -0,0 +1,43 @@ +#ifndef _DICT_MONGODB_INCLUDED_ +#define _DICT_MONGODB_INCLUDED_ + +/*++ +/* NAME +/* dict_mongodb 3h +/* SUMMARY +/* dictionary interface to mongodb databases +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +#define DICT_TYPE_MONGODB "mongodb" + +extern DICT *dict_mongodb_open(const char *, int, int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Hamid Maadani (hamid@dexo.tech) +/* Dextrous Technologies, LLC +/* +/* Edited by: +/* Wietse Venema +/* porcupine.org +/* +/* Based on prior work by: +/* Stephan Ferraro +/* Aionda GmbH +/*--*/ + +#endif diff --git a/src/global/dict_mysql.c b/src/global/dict_mysql.c index 3c8fe4f..133cc0d 100644 --- a/src/global/dict_mysql.c +++ b/src/global/dict_mysql.c @@ -83,6 +83,10 @@ #include #include +#if !defined(MYSQL_VERSION_ID) || MYSQL_VERSION_ID < 40000 +#error "MySQL versions <4 are no longer supported" +#endif + #ifdef STRCASECMP_IN_STRINGS_H #include #endif @@ -147,9 +151,11 @@ typedef struct { char *username; char *password; char *dbname; + char *charset; + int retry_interval; + int idle_interval; ARGV *hosts; PLMYSQL *pldb; -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 HOST *active_host; char *tls_cert_file; char *tls_key_file; @@ -158,7 +164,6 @@ typedef struct { char *tls_ciphers; #if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT) int tls_verify_cert; -#endif #endif int require_result_set; } DICT_MYSQL; @@ -171,15 +176,15 @@ typedef struct { #define TYPEINET (1<<1) #define RETRY_CONN_MAX 100 -#define RETRY_CONN_INTV 60 /* 1 minute */ -#define IDLE_CONN_INTV 60 /* 1 minute */ +#define DEF_RETRY_INTV 60 /* 1 minute */ +#define DEF_IDLE_INTV 60 /* 1 minute */ /* internal function declarations */ static PLMYSQL *plmysql_init(ARGV *); static int plmysql_query(DICT_MYSQL *, const char *, VSTRING *, MYSQL_RES **); static void plmysql_dealloc(PLMYSQL *); static void plmysql_close_host(HOST *); -static void plmysql_down_host(HOST *); +static void plmysql_down_host(HOST *, int); static void plmysql_connect_single(DICT_MYSQL *, HOST *); static const char *dict_mysql_lookup(DICT *, const char *); DICT *dict_mysql_open(const char *, int, int); @@ -205,13 +210,21 @@ static void dict_mysql_quote(DICT *dict, const char *name, VSTRING *result) buflen = 2 * len + 1; VSTRING_SPACE(result, buflen); -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 - if (dict_mysql->active_host) - mysql_real_escape_string(dict_mysql->active_host->db, - vstring_end(result), name, len); - else + if (dict_mysql->active_host == 0) + msg_panic("dict_mysql_quote: no active host"); +#if MYSQL_VERSION_ID >= 50706 && !defined(MARIADB_VERSION_ID) + mysql_real_escape_string_quote(dict_mysql->active_host->db, + vstring_end(result), name, len, '\''); +#else + if (mysql_real_escape_string(dict_mysql->active_host->db, + vstring_end(result), name, len) == + (unsigned long) -1) { + msg_warn("dict_mysql: host (%s) cannot escape input string: >%s<", + dict_mysql->active_host->hostname, + mysql_error(dict_mysql->active_host->db)); + dict_mysql->active_host->stat = STATFAIL; + } #endif - mysql_escape_string(vstring_end(result), name, len); VSTRING_SKIP(result); } @@ -231,7 +244,6 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name) int numrows; int expansion; const char *r; - db_quote_callback_t quote_func = dict_mysql_quote; int domain_rc; dict->error = 0; @@ -241,7 +253,7 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name) */ #ifdef SNAPSHOT if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 - && !valid_utf8_string(name, strlen(name))) { + && !valid_utf8_stringz(name)) { if (msg_verbose) msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", myname, dict_mysql->parser->name, name); @@ -291,11 +303,8 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name) * quoting happens separately for each connection, we don't bother with * quoting... */ -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 - quote_func = 0; -#endif if (!db_common_expand(dict_mysql->ctx, dict_mysql->query, - name, 0, query, quote_func)) + name, 0, query, (db_quote_callback_t) 0)) return (0); /* do the query - set dict->error & cleanup if there's an error */ @@ -439,8 +448,12 @@ static int plmysql_query(DICT_MYSQL *dict_mysql, { HOST *host; MYSQL_RES *first_result = 0; + + /* In case all hosts are down. */ int query_error = 1; + errno = ENOTSUP; + /* * Helper to avoid spamming the log with warnings. */ @@ -454,8 +467,6 @@ static int plmysql_query(DICT_MYSQL *dict_mysql, while ((host = dict_mysql_get_active(dict_mysql)) != NULL) { -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 - /* * The active host is used to escape strings in the context of the * active connection's character encoding. @@ -465,8 +476,14 @@ static int plmysql_query(DICT_MYSQL *dict_mysql, VSTRING_TERMINATE(query); db_common_expand(dict_mysql->ctx, dict_mysql->query, name, 0, query, dict_mysql_quote); + /* Check for potential dict_mysql_quote() failure. */ + if (host->stat == STATFAIL) { + plmysql_down_host(host, dict_mysql->retry_interval); + continue; + } + if (msg_verbose) + msg_info("expanded and quoted query: >%s<", vstring_str(query)); dict_mysql->active_host = 0; -#endif query_error = 0; errno = 0; @@ -546,7 +563,7 @@ static int plmysql_query(DICT_MYSQL *dict_mysql, * See what we got. */ if (query_error) { - plmysql_down_host(host); + plmysql_down_host(host, dict_mysql->retry_interval); if (errno == 0) errno = ENOTSUP; if (first_result) { @@ -559,7 +576,7 @@ static int plmysql_query(DICT_MYSQL *dict_mysql, dict_mysql->dict.type, dict_mysql->dict.name, host->hostname); event_request_timer(dict_mysql_event, (void *) host, - IDLE_CONN_INTV); + dict_mysql->idle_interval); break; } } @@ -581,7 +598,6 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) mysql_options(host->db, MYSQL_READ_DEFAULT_FILE, dict_mysql->option_file); if (dict_mysql->option_group && dict_mysql->option_group[0]) mysql_options(host->db, MYSQL_READ_DEFAULT_GROUP, dict_mysql->option_group); -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 if (dict_mysql->tls_key_file || dict_mysql->tls_cert_file || dict_mysql->tls_CAfile || dict_mysql->tls_CApath || dict_mysql->tls_ciphers) mysql_ssl_set(host->db, @@ -592,7 +608,6 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) if (dict_mysql->tls_verify_cert != -1) mysql_options(host->db, DICT_MYSQL_SSL_VERIFY_SERVER_CERT, &dict_mysql->tls_verify_cert); -#endif #endif if (mysql_real_connect(host->db, (host->type == TYPEINET ? host->name : 0), @@ -602,6 +617,12 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) host->port, (host->type == TYPEUNIX ? host->name : 0), CLIENT_MULTI_RESULTS)) { + if (mysql_set_character_set(host->db, dict_mysql->charset) != 0) { + msg_warn("dict_mysql: mysql_set_character_set '%s' failed: %s", + dict_mysql->charset, mysql_error(host->db)); + plmysql_down_host(host, dict_mysql->retry_interval); + return; + } if (msg_verbose) msg_info("dict_mysql: successful connection to host %s", host->hostname); @@ -609,7 +630,7 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host) } else { msg_warn("connect to mysql server %s: %s", host->hostname, mysql_error(host->db)); - plmysql_down_host(host); + plmysql_down_host(host, dict_mysql->retry_interval); } } @@ -625,11 +646,11 @@ static void plmysql_close_host(HOST *host) * plmysql_down_host - close a failed connection AND set a "stay away from * this host" timer */ -static void plmysql_down_host(HOST *host) +static void plmysql_down_host(HOST *host, int retry_interval) { mysql_close(host->db); host->db = 0; - host->ts = time((time_t *) 0) + RETRY_CONN_INTV; + host->ts = time((time_t *) 0) + retry_interval; host->stat = STATFAIL; event_cancel_timer(dict_mysql_event, (void *) host); } @@ -646,10 +667,14 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf) dict_mysql->username = cfg_get_str(p, "user", "", 0, 0); dict_mysql->password = cfg_get_str(p, "password", "", 0, 0); dict_mysql->dbname = cfg_get_str(p, "dbname", "", 1, 0); + dict_mysql->charset = cfg_get_str(p, "charset", "utf8mb4", 1, 0); + dict_mysql->retry_interval = cfg_get_int(p, "retry_interval", + DEF_RETRY_INTV, 1, 0); + dict_mysql->idle_interval = cfg_get_int(p, "idle_interval", + DEF_IDLE_INTV, 1, 0); dict_mysql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0); dict_mysql->option_file = cfg_get_str(p, "option_file", NULL, 0, 0); dict_mysql->option_group = cfg_get_str(p, "option_group", "client", 0, 0); -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 dict_mysql->tls_key_file = cfg_get_str(p, "tls_key_file", NULL, 0, 0); dict_mysql->tls_cert_file = cfg_get_str(p, "tls_cert_file", NULL, 0, 0); dict_mysql->tls_CAfile = cfg_get_str(p, "tls_CAfile", NULL, 0, 0); @@ -657,7 +682,6 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf) dict_mysql->tls_ciphers = cfg_get_str(p, "tls_ciphers", NULL, 0, 0); #if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT) dict_mysql->tls_verify_cert = cfg_get_bool(p, "tls_verify_cert", -1); -#endif #endif dict_mysql->require_result_set = cfg_get_bool(p, "require_result_set", 1); @@ -741,9 +765,7 @@ DICT *dict_mysql_open(const char *name, int open_flags, int dict_flags) dict_mysql->dict.flags = dict_flags; dict_mysql->parser = parser; mysql_parse_config(dict_mysql, name); -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 dict_mysql->active_host = 0; -#endif dict_mysql->pldb = plmysql_init(dict_mysql->hosts); if (dict_mysql->pldb == NULL) msg_fatal("couldn't initialize pldb!\n"); @@ -826,13 +848,13 @@ static void dict_mysql_close(DICT *dict) myfree(dict_mysql->username); myfree(dict_mysql->password); myfree(dict_mysql->dbname); + myfree(dict_mysql->charset); myfree(dict_mysql->query); myfree(dict_mysql->result_format); if (dict_mysql->option_file) myfree(dict_mysql->option_file); if (dict_mysql->option_group) myfree(dict_mysql->option_group); -#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000 if (dict_mysql->tls_key_file) myfree(dict_mysql->tls_key_file); if (dict_mysql->tls_cert_file) @@ -843,7 +865,6 @@ static void dict_mysql_close(DICT *dict) myfree(dict_mysql->tls_CApath); if (dict_mysql->tls_ciphers) myfree(dict_mysql->tls_ciphers); -#endif if (dict_mysql->hosts) argv_free(dict_mysql->hosts); if (dict_mysql->ctx) diff --git a/src/global/dict_pgsql.c b/src/global/dict_pgsql.c index 5992135..c626854 100644 --- a/src/global/dict_pgsql.c +++ b/src/global/dict_pgsql.c @@ -108,18 +108,18 @@ #define TYPEUNIX (1<<0) #define TYPEINET (1<<1) -#define TYPECONNSTRING (1<<2) +#define TYPECONNSTR (1<<2) #define RETRY_CONN_MAX 100 -#define RETRY_CONN_INTV 60 /* 1 minute */ -#define IDLE_CONN_INTV 60 /* 1 minute */ +#define DEF_RETRY_INTV 60 /* 1 minute */ +#define DEF_IDLE_INTV 60 /* 1 minute */ typedef struct { PGconn *db; char *hostname; char *name; char *port; - unsigned type; /* TYPEUNIX | TYPEINET | TYPECONNSTRING */ + unsigned type; /* TYPEUNIX | TYPEINET | TYPECONNSTR */ unsigned stat; /* STATUNTRIED | STATFAIL | STATCUR */ time_t ts; /* used for attempting reconnection */ } HOST; @@ -140,6 +140,8 @@ typedef struct { char *password; char *dbname; char *encoding; + int retry_interval; + int idle_interval; char *table; ARGV *hosts; PLPGSQL *pldb; @@ -152,12 +154,11 @@ typedef struct { /* internal function declarations */ static PLPGSQL *plpgsql_init(ARGV *); -static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *, char *, - char *, char *, char *); +static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *); static void plpgsql_dealloc(PLPGSQL *); static void plpgsql_close_host(HOST *); -static void plpgsql_down_host(HOST *); -static void plpgsql_connect_single(HOST *, char *, char *, char *, char *); +static void plpgsql_down_host(HOST *, int); +static void plpgsql_connect_single(DICT_PGSQL *, HOST *); static const char *dict_pgsql_lookup(DICT *, const char *); DICT *dict_pgsql_open(const char *, int, int); static void dict_pgsql_close(DICT *); @@ -280,7 +281,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) */ #ifdef SNAPSHOT if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 - && !valid_utf8_string(name, strlen(name))) { + && !valid_utf8_stringz(name)) { if (msg_verbose) msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", myname, dict_pgsql->parser->name, name); @@ -324,11 +325,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) return (0); /* do the query - set dict->error & cleanup if there's an error */ - if ((query_res = plpgsql_query(dict_pgsql, name, query, - dict_pgsql->dbname, - dict_pgsql->encoding, - dict_pgsql->username, - dict_pgsql->password)) == 0) { + if ((query_res = plpgsql_query(dict_pgsql, name, query)) == 0) { dict->error = DICT_ERR_RETRY; return 0; } @@ -404,8 +401,7 @@ static HOST *dict_pgsql_find_host(PLPGSQL *PLDB, unsigned stat, unsigned type) /* dict_pgsql_get_active - get an active connection */ -static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding, - char *username, char *password) +static HOST *dict_pgsql_get_active(DICT_PGSQL *dict_pgsql, PLPGSQL *PLDB) { const char *myname = "dict_pgsql_get_active"; HOST *host; @@ -414,7 +410,7 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding, /* try the active connections first; prefer the ones to UNIX sockets */ if ((host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPEUNIX)) != NULL || (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPEINET)) != NULL || - (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTRING)) != NULL) { + (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTR)) != NULL) { if (msg_verbose) msg_info("%s: found active connection to host %s", myname, host->hostname); @@ -432,11 +428,11 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding, (host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL, TYPEINET)) != NULL || (host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL, - TYPECONNSTRING)) != NULL)) { + TYPECONNSTR)) != NULL)) { if (msg_verbose) msg_info("%s: attempting to connect to host %s", myname, host->hostname); - plpgsql_connect_single(host, dbname, encoding, username, password); + plpgsql_connect_single(dict_pgsql, host); if (host->stat == STATACTIVE) return host; } @@ -464,18 +460,14 @@ static void dict_pgsql_event(int unused_event, void *context) static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, const char *name, - VSTRING *query, - char *dbname, - char *encoding, - char *username, - char *password) + VSTRING *query) { PLPGSQL *PLDB = dict_pgsql->pldb; HOST *host; PGSQL_RES *res = 0; ExecStatusType status; - while ((host = dict_pgsql_get_active(PLDB, dbname, encoding, username, password)) != NULL) { + while ((host = dict_pgsql_get_active(dict_pgsql, PLDB)) != NULL) { /* * The active host is used to escape strings in the context of the @@ -490,7 +482,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, /* Check for potential dict_pgsql_quote() failure. */ if (host->stat == STATFAIL) { - plpgsql_down_host(host); + plpgsql_down_host(host, dict_pgsql->retry_interval); continue; } @@ -528,7 +520,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, msg_info("dict_pgsql: successful query from host %s", host->hostname); event_request_timer(dict_pgsql_event, (void *) host, - IDLE_CONN_INTV); + dict_pgsql->idle_interval); return (res); case PGRES_FATAL_ERROR: msg_warn("pgsql query failed: fatal error from host %s: %s", @@ -559,7 +551,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, */ if (res != 0) PQclear(res); - plpgsql_down_host(host); + plpgsql_down_host(host, dict_pgsql->retry_interval); } return (0); @@ -570,24 +562,25 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, * used to reconnect to a single database when one is down or none is * connected yet. Log all errors and set the stat field of host accordingly */ -static void plpgsql_connect_single(HOST *host, char *dbname, char *encoding, char *username, char *password) +static void plpgsql_connect_single(DICT_PGSQL *dict_pgsql, HOST *host) { - if (host->type == TYPECONNSTRING) { + if (host->type == TYPECONNSTR) { host->db = PQconnectdb(host->name); } else { host->db = PQsetdbLogin(host->name, host->port, NULL, NULL, - dbname, username, password); + dict_pgsql->dbname, dict_pgsql->username, + dict_pgsql->password); } if (host->db == NULL || PQstatus(host->db) != CONNECTION_OK) { msg_warn("connect to pgsql server %s: %s", host->hostname, PQerrorMessage(host->db)); - plpgsql_down_host(host); + plpgsql_down_host(host, dict_pgsql->retry_interval); return; } - if (PQsetClientEncoding(host->db, encoding) != 0) { + if (PQsetClientEncoding(host->db, dict_pgsql->encoding) != 0) { msg_warn("dict_pgsql: cannot set the encoding to %s, skipping %s", - encoding, host->hostname); - plpgsql_down_host(host); + dict_pgsql->encoding, host->hostname); + plpgsql_down_host(host, dict_pgsql->retry_interval); return; } if (msg_verbose) @@ -611,12 +604,12 @@ static void plpgsql_close_host(HOST *host) * plpgsql_down_host - close a failed connection AND set a "stay away from * this host" timer. */ -static void plpgsql_down_host(HOST *host) +static void plpgsql_down_host(HOST *host, int retry_interval) { if (host->db) PQfinish(host->db); host->db = 0; - host->ts = time((time_t *) 0) + RETRY_CONN_INTV; + host->ts = time((time_t *) 0) + retry_interval; host->stat = STATFAIL; event_cancel_timer(dict_pgsql_event, (void *) host); } @@ -635,6 +628,10 @@ static void pgsql_parse_config(DICT_PGSQL *dict_pgsql, const char *pgsqlcf) dict_pgsql->password = cfg_get_str(p, "password", "", 0, 0); dict_pgsql->dbname = cfg_get_str(p, "dbname", "", 1, 0); dict_pgsql->encoding = cfg_get_str(p, "encoding", "UTF8", 1, 0); + dict_pgsql->retry_interval = cfg_get_int(p, "retry_interval", + DEF_RETRY_INTV, 1, 0); + dict_pgsql->idle_interval = cfg_get_int(p, "idle_interval", + DEF_IDLE_INTV, 1, 0); dict_pgsql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0); /* @@ -764,7 +761,7 @@ static HOST *host_init(const char *hostname) * Modern syntax: "postgresql://connection-info". */ if (strncmp(d, "postgresql:", 11) == 0) { - host->type = TYPECONNSTRING; + host->type = TYPECONNSTR; host->name = mystrdup(d); host->port = 0; } diff --git a/src/global/dict_sqlite.c b/src/global/dict_sqlite.c index 677d05a..7d6608a 100644 --- a/src/global/dict_sqlite.c +++ b/src/global/dict_sqlite.c @@ -149,7 +149,7 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name) * Don't frustrate future attempts to make Postfix UTF-8 transparent. */ if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 - && !valid_utf8_string(name, strlen(name))) { + && !valid_utf8_stringz(name)) { if (msg_verbose) msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", myname, dict_sqlite->parser->name, name); diff --git a/src/global/mail_addr_find.c b/src/global/mail_addr_find.c index afbccd5..c7e5545 100644 --- a/src/global/mail_addr_find.c +++ b/src/global/mail_addr_find.c @@ -442,8 +442,8 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp, /* * Try localpart@ even if the domain is not local. */ - if ((strategy & MA_FIND_LOCALPART_AT) != 0 \ - &&result == 0 && path->error == 0) + if ((strategy & MA_FIND_LOCALPART_AT) != 0 + && result == 0 && path->error == 0) result = find_local(path, ratsign, 1, int_full_key, int_bare_key, query_form, extp, &saved_ext, ext_addr_buf); diff --git a/src/global/mail_date.c b/src/global/mail_date.c index 55d8907..439a0ea 100644 --- a/src/global/mail_date.c +++ b/src/global/mail_date.c @@ -10,7 +10,7 @@ /* time_t when; /* DESCRIPTION /* mail_date() converts the time specified in \fIwhen\fR to the -/* form: "Mon, 9 Dec 1996 05:38:26 -0500 (EST)" and returns +/* form: "Mon, 09 Dec 1996 05:38:26 -0500 (EST)" and returns /* a pointer to the result. The result is overwritten upon /* each call. /* DIAGNOSTICS @@ -98,8 +98,13 @@ const char *mail_date(time_t when) * First, format the date and wall-clock time. XXX The %e format (day of * month, leading zero replaced by blank) isn't in my POSIX book, but * many vendors seem to support it. + * + * The RFC 5322 Date and Time Specification recommends (i.e., should) "that + * a single space be used in each place that FWS appears". To avoid a + * potentially breaking change, we prefer the %d (two-digit day) format, + * i.e. days 1-9 now have a leading zero instead of a leading space. */ -#ifdef MISSING_STRFTIME_E +#if defined(MISSING_STRFTIME_E) || defined(TWO_DIGIT_DAY_IN_DATE_TIME) #define STRFTIME_FMT "%a, %d %b %Y %H:%M:%S " #else #define STRFTIME_FMT "%a, %e %b %Y %H:%M:%S " diff --git a/src/global/mail_dict.c b/src/global/mail_dict.c index c640a80..55ac5dc 100644 --- a/src/global/mail_dict.c +++ b/src/global/mail_dict.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,9 @@ static const DICT_OPEN_INFO dict_open_info[] = { #ifdef HAS_SQLITE DICT_TYPE_SQLITE, dict_sqlite_open, 0, #endif +#ifdef HAS_MONGODB + DICT_TYPE_MONGODB, dict_mongodb_open, 0, +#endif #endif /* !USE_DYNAMIC_MAPS */ DICT_TYPE_MEMCACHE, dict_memcache_open, 0, 0, diff --git a/src/global/mail_params.c b/src/global/mail_params.c index 81aee73..2a7f84c 100644 --- a/src/global/mail_params.c +++ b/src/global/mail_params.c @@ -159,6 +159,7 @@ /* char *var_maillog_file_pfxs; /* char *var_maillog_file_comp; /* char *var_maillog_file_stamp; +/* char *var_maillog_file_perms; /* char *var_postlog_service; /* /* char *var_dnssec_probe; @@ -226,6 +227,7 @@ #include #include #include +#include /* Global library. */ @@ -375,6 +377,7 @@ char *var_maillog_file; char *var_maillog_file_pfxs; char *var_maillog_file_comp; char *var_maillog_file_stamp; +char *var_maillog_file_perms; char *var_postlog_service; char *var_dnssec_probe; @@ -515,9 +518,11 @@ static void check_mail_owner(void) */ if ((pwd = getpwuid(var_owner_uid)) != 0 && strcmp(pwd->pw_name, var_mail_owner) != 0) - msg_fatal("file %s/%s: parameter %s: user %s has same user ID as %s", + msg_fatal("file %s/%s: parameter %s: user %s has the same" + " user ID %ld as user %s", var_config_dir, MAIN_CONF_FILE, - VAR_MAIL_OWNER, var_mail_owner, pwd->pw_name); + VAR_MAIL_OWNER, var_mail_owner, + (long) var_owner_uid, pwd->pw_name); } /* check_sgid_group - lookup setgid group attributes and validate */ @@ -542,9 +547,11 @@ static void check_sgid_group(void) */ if ((grp = getgrgid(var_sgid_gid)) != 0 && strcmp(grp->gr_name, var_sgid_group) != 0) - msg_fatal("file %s/%s: parameter %s: group %s has same group ID as %s", + msg_fatal("file %s/%s: parameter %s: group %s has the same" + " group ID %ld as group %s", var_config_dir, MAIN_CONF_FILE, - VAR_SGID_GROUP, var_sgid_group, grp->gr_name); + VAR_SGID_GROUP, var_sgid_group, + (long) var_sgid_gid, grp->gr_name); } /* check_overlap - disallow UID or GID sharing */ @@ -729,6 +736,7 @@ void mail_params_init() VAR_MAILLOG_FILE_PFXS, DEF_MAILLOG_FILE_PFXS, &var_maillog_file_pfxs, 1, 0, VAR_MAILLOG_FILE_COMP, DEF_MAILLOG_FILE_COMP, &var_maillog_file_comp, 1, 0, VAR_MAILLOG_FILE_STAMP, DEF_MAILLOG_FILE_STAMP, &var_maillog_file_stamp, 1, 0, + VAR_MAILLOG_FILE_PERMS, DEF_MAILLOG_FILE_PERMS, &var_maillog_file_perms, 1, 0, VAR_POSTLOG_SERVICE, DEF_POSTLOG_SERVICE, &var_postlog_service, 1, 0, VAR_DNSSEC_PROBE, DEF_DNSSEC_PROBE, &var_dnssec_probe, 0, 0, VAR_KNOWN_TCP_PORTS, DEF_KNOWN_TCP_PORTS, &var_known_tcp_ports, 0, 0, @@ -979,6 +987,9 @@ void mail_params_init() dict_db_cache_size = var_db_read_buf; dict_lmdb_map_size = var_lmdb_map_size; inet_windowsize = var_inet_windowsize; + if (set_logwriter_create_perms(var_maillog_file_perms) < 0) + msg_warn("ignoring bad permissions: %s = %s", + VAR_MAILLOG_FILE_PERMS, var_maillog_file_perms); /* * Variables whose defaults are determined at runtime, after other diff --git a/src/global/mail_params.h b/src/global/mail_params.h index 3064b01..1f03b0b 100644 --- a/src/global/mail_params.h +++ b/src/global/mail_params.h @@ -1321,6 +1321,10 @@ extern bool var_smtpd_tls_ask_ccert; #define DEF_SMTPD_TLS_RCERT 0 extern bool var_smtpd_tls_req_ccert; +#define VAR_SMTPD_TLS_ENABLE_RPK "smtpd_tls_enable_rpk" +#define DEF_SMTPD_TLS_ENABLE_RPK 0 +extern bool var_smtpd_tls_enable_rpk; + #define VAR_SMTPD_TLS_CCERT_VD "smtpd_tls_ccert_verifydepth" #define DEF_SMTPD_TLS_CCERT_VD 9 extern int var_smtpd_tls_ccert_vd; @@ -1555,6 +1559,12 @@ extern char *var_smtp_tls_mand_excl; "{md5} : {sha256}}" extern char *var_smtp_tls_fpt_dgst; +#define VAR_SMTP_TLS_ENABLE_RPK "smtp_tls_enable_rpk" +#define DEF_SMTP_TLS_ENABLE_RPK 0 +#define VAR_LMTP_TLS_ENABLE_RPK "lmtp_tls_enable_rpk" +#define DEF_LMTP_TLS_ENABLE_RPK 0 +extern bool var_smtp_tls_enable_rpk; + #define VAR_SMTP_TLS_TAFILE "smtp_tls_trust_anchor_file" #define DEF_SMTP_TLS_TAFILE "" #define VAR_LMTP_TLS_TAFILE "lmtp_tls_trust_anchor_file" @@ -1745,6 +1755,12 @@ extern bool var_smtp_sasl_enable; #define DEF_SMTP_SASL_PASSWD "" extern char *var_smtp_sasl_passwd; +#define VAR_SMTP_SASL_PASSWD_RES_DELIM "smtp_sasl_password_result_delimiter" +#define DEF_SMTP_SASL_PASSWD_RES_DELIM ":" +#define VAR_LMTP_SASL_PASSWD_RES_DELIM "lmtp_sasl_password_result_delimiter" +#define DEF_LMTP_SASL_PASSWD_RES_DELIM DEF_SMTP_SASL_PASSWD_RES_DELIM +extern char *var_smtp_sasl_passwd_res_delim; + #define VAR_SMTP_SASL_OPTS "smtp_sasl_security_options" #define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous" extern char *var_smtp_sasl_opts; @@ -2437,7 +2453,7 @@ extern char *var_smtpd_exp_filter; extern bool var_smtpd_peername_lookup; #define VAR_SMTPD_FORBID_UNAUTH_PIPE "smtpd_forbid_unauth_pipelining" -#define DEF_SMTPD_FORBID_UNAUTH_PIPE 0 +#define DEF_SMTPD_FORBID_UNAUTH_PIPE 1 extern bool var_smtpd_forbid_unauth_pipe; /* @@ -3072,6 +3088,10 @@ extern bool var_disable_mime_input; #define DEF_DISABLE_MIME_OCONV 0 extern bool var_disable_mime_oconv; +#define VAR_FORCE_MIME_ICONV "force_mime_input_conversion" +#define DEF_FORCE_MIME_ICONV 0 +extern bool var_force_mime_iconv; + #define VAR_STRICT_8BITMIME "strict_8bitmime" #define DEF_STRICT_8BITMIME 0 extern bool var_strict_8bitmime; @@ -3982,6 +4002,10 @@ extern bool var_tlsp_tls_ask_ccert; #define DEF_TLSP_TLS_RCERT "$" VAR_SMTPD_TLS_RCERT extern bool var_tlsp_tls_req_ccert; +#define VAR_TLSP_TLS_ENABLE_RPK "tlsproxy_tls_enable_rpk" +#define DEF_TLSP_TLS_ENABLE_RPK "$" VAR_SMTPD_TLS_ENABLE_RPK +extern bool var_tlsp_tls_enable_rpk; + #define VAR_TLSP_TLS_CCERT_VD "tlsproxy_tls_ccert_verifydepth" #define DEF_TLSP_TLS_CCERT_VD "$" VAR_SMTPD_TLS_CCERT_VD extern int var_tlsp_tls_ccert_vd; @@ -4282,7 +4306,7 @@ extern char *var_smtpd_dns_re_filter; * Backwards compatibility. */ #define VAR_SMTPD_FORBID_BARE_LF "smtpd_forbid_bare_newline" -#define DEF_SMTPD_FORBID_BARE_LF "no" +#define DEF_SMTPD_FORBID_BARE_LF "normalize" #define VAR_SMTPD_FORBID_BARE_LF_EXCL "smtpd_forbid_bare_newline_exclusions" #define DEF_SMTPD_FORBID_BARE_LF_EXCL "$" VAR_MYNETWORKS @@ -4379,6 +4403,10 @@ extern char *var_maillog_file_comp; #define DEF_MAILLOG_FILE_STAMP "%Y%m%d-%H%M%S" extern char *var_maillog_file_stamp; +#define VAR_MAILLOG_FILE_PERMS "maillog_file_permissions" +#define DEF_MAILLOG_FILE_PERMS "0600" +extern char *var_maillog_file_perms; + #define VAR_POSTLOG_SERVICE "postlog_service_name" #define DEF_POSTLOG_SERVICE MAIL_SERVICE_POSTLOG extern char *var_postlog_service; diff --git a/src/global/mail_proto.h b/src/global/mail_proto.h index 315a2e1..bea0886 100644 --- a/src/global/mail_proto.h +++ b/src/global/mail_proto.h @@ -62,6 +62,13 @@ #define MAIL_SERVICE_TLSPROXY "tlsproxy" #define MAIL_SERVICE_POSTLOG "postlog" + /* + * Process names: convention is to use the basename of an executable file, + * but there is nothing to enforce that. + */ +#define MAIL_PROC_NAME_SMTP "smtp" +#define MAIL_PROC_NAME_LMTP "lmtp" + /* * Mail source classes. Used to specify policy decisions for content * inspection and SMTPUTF8 detection. diff --git a/src/global/mail_version.h b/src/global/mail_version.h index 9eda667..9e08896 100644 --- a/src/global/mail_version.h +++ b/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20240304" -#define MAIL_VERSION_NUMBER "3.8.6" +#define MAIL_RELEASE_DATE "20240306" +#define MAIL_VERSION_NUMBER "3.9" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/src/global/maillog_client.c b/src/global/maillog_client.c index 7f79a1f..34952ef 100644 --- a/src/global/maillog_client.c +++ b/src/global/maillog_client.c @@ -58,7 +58,7 @@ /* unitialized and the process environment does not specify /* POSTLOG_SERVICE, the program will log to the syslog service /* instead. -/* .IP "myhostname (default: see postconf -d output)" +/* .IP "myhostname (default: see 'postconf -d' output)" /* The internet hostname of this mail system. /* .IP "postlog_service_name (postlog)" /* The name of the internal postlog logging service. diff --git a/src/global/maps.c b/src/global/maps.c index 790396b..d237002 100644 --- a/src/global/maps.c +++ b/src/global/maps.c @@ -195,8 +195,12 @@ const char *maps_find(MAPS *maps, const char *name, int flags) for (map_name = maps->argv->argv; *map_name; map_name++) { if ((dict = dict_handle(*map_name)) == 0) msg_panic("%s: dictionary not found: %s", myname, *map_name); - if (flags != 0 && (dict->flags & flags) == 0) + if (flags != 0 && (dict->flags & flags) == 0) { + if (msg_verbose) + msg_info("%s: %s: skipping %s lookup for %s", + myname, maps->title, *map_name, name); continue; + } if ((expansion = dict_get(dict, name)) != 0) { if (*expansion == 0) { msg_warn("%s lookup of %s returns an empty string result", @@ -252,8 +256,12 @@ const char *maps_file_find(MAPS *maps, const char *name, int flags) if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) == 0) msg_panic("%s: %s: opened without DICT_FLAG_SRC_RHS_IS_FILE", myname, maps->title); - if (flags != 0 && (dict->flags & flags) == 0) + if (flags != 0 && (dict->flags & flags) == 0) { + if (msg_verbose) + msg_info("%s: %s: skipping %s lookup for %s", + myname, maps->title, *map_name, name); continue; + } if ((expansion = dict_get(dict, name)) != 0) { if (*expansion == 0) { msg_warn("%s lookup of %s returns an empty string result", diff --git a/src/global/wildcard_inet_addr.c b/src/global/wildcard_inet_addr.c index 97f6c46..0a3c37a 100644 --- a/src/global/wildcard_inet_addr.c +++ b/src/global/wildcard_inet_addr.c @@ -11,7 +11,7 @@ /* wildcard_inet_addr() determines all wild-card addresses /* for all supported address families. /* DIAGNOSTICS -/* Fatal errors: out of memory. +/* Fatal errors: out of memory; no wildcard addresses. /* SEE ALSO /* inet_addr_list(3) address list management /* LICENSE diff --git a/src/local/command.c b/src/local/command.c index 4781daf..368307d 100644 --- a/src/local/command.c +++ b/src/local/command.c @@ -17,7 +17,8 @@ /* Duplicate commands for the same recipient are suppressed. /* A limited amount of information is exported via the environment: /* HOME, SHELL, LOGNAME, USER, EXTENSION, DOMAIN, RECIPIENT (entire -/* address) LOCAL (just the local part) and SENDER. The exported +/* address) LOCAL (just the local part), SENDER, and ENVID +/* (see RFC 3461). The exported /* information is censored with var_cmd_filter. /* /* Arguments: @@ -169,6 +170,8 @@ int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, const char *comma if (state.msg_attr.rcpt.orig_addr && state.msg_attr.rcpt.orig_addr[0]) argv_add(env, "ORIGINAL_RECIPIENT", state.msg_attr.rcpt.orig_addr, ARGV_END); + if (state.request->dsn_envid[0]) + argv_add(env, "ENVID", state.request->dsn_envid, ARGV_END); #define EXPORT_REQUEST(name, value) \ if ((value)[0]) argv_add(env, (name), (value), ARGV_END); diff --git a/src/local/local.c b/src/local/local.c index 32bdea7..10b8082 100644 --- a/src/local/local.c +++ b/src/local/local.c @@ -207,27 +207,30 @@ /* is specified with the \fBcommand_expansion_filter\fR configuration /* parameter. /* .IP \fBSHELL\fR -/* The recipient user's login shell. +/* The envelope recipient user's login shell. /* .IP \fBHOME\fR -/* The recipient user's home directory. +/* The envelope recipient user's home directory. /* .IP \fBUSER\fR -/* The bare recipient name. +/* The bare envelope recipient name. /* .IP \fBEXTENSION\fR -/* The optional recipient address extension. +/* The optional envelope recipient address extension. /* .IP \fBDOMAIN\fR -/* The recipient address domain part. +/* The envelope recipient address domain part. /* .IP \fBLOGNAME\fR -/* The bare recipient name. +/* The bare envelope recipient name. /* .IP \fBLOCAL\fR -/* The entire recipient address localpart (text to the left of the -/* rightmost @ character). +/* The entire envelope recipient address localpart (text to +/* the left of the rightmost @ character). /* .IP \fBORIGINAL_RECIPIENT\fR -/* The entire recipient address, before any address rewriting -/* or aliasing (Postfix 2.5 and later). +/* The entire envelope recipient address, before any address +/* rewriting or aliasing (Postfix 2.5 and later). /* .IP \fBRECIPIENT\fR -/* The entire recipient address. +/* The entire envelope recipient address. /* .IP \fBSENDER\fR -/* The entire sender address. +/* The entire envelope sender address. +/* .IP \fBENVID\fR +/* The optional RFC 3461 envelope ID. Available as of Postfix +/* 3.9. /* .PP /* Additional remote client information is made available via /* the following environment variables: @@ -413,7 +416,9 @@ /* home_mailbox, mail_spool_directory, fallback_transport_maps, /* fallback_transport, and luser_relay. /* .IP "\fBalias_maps (see 'postconf -d' output)\fR" -/* The alias databases that are used for \fBlocal\fR(8) delivery. +/* Optional lookup tables with aliases that apply only to \fBlocal\fR(8) +/* recipients; this is unlike virtual_alias_maps that apply to all +/* recipients: \fBlocal\fR(8), virtual, and remote. /* .IP "\fBforward_path (see 'postconf -d' output)\fR" /* The \fBlocal\fR(8) delivery agent search list for finding a .forward /* file with user-specified delivery methods. diff --git a/src/master/master.c b/src/master/master.c index 1fc3fe9..b6afe3f 100644 --- a/src/master/master.c +++ b/src/master/master.c @@ -135,13 +135,13 @@ /* The external command to execute when a Postfix daemon program is /* invoked with the -D option. /* .IP "\fBinet_interfaces (all)\fR" -/* The network interface addresses that this mail system receives -/* mail on. -/* .IP "\fBinet_protocols (see 'postconf -d output')\fR" +/* The local network interface addresses that this mail system +/* receives mail on. +/* .IP "\fBinet_protocols (see 'postconf -d' output)\fR" /* The Internet protocols Postfix will attempt to use when making /* or accepting connections. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* .IP "\fBmail_owner (postfix)\fR" @@ -495,7 +495,7 @@ int main(int argc, char **argv) vstring_sprintf(lock_path, "%s/%s.pid", DEF_PID_DIR, var_procname); if (test_lock && access(vstring_str(lock_path), F_OK) < 0) exit(0); - lock_fp = open_lock(vstring_str(lock_path), O_RDWR | O_CREAT, 0644, why); + lock_fp = open_lock(vstring_str(lock_path), O_RDWR | O_CREAT, 0600, why); if (test_lock) exit(lock_fp ? 0 : 1); if (lock_fp == 0) @@ -513,7 +513,7 @@ int main(int argc, char **argv) vstring_sprintf(data_lock_path, "%s/%s.lock", var_data_dir, var_procname); set_eugid(var_owner_uid, var_owner_gid); data_lock_fp = - open_lock(vstring_str(data_lock_path), O_RDWR | O_CREAT, 0644, why); + open_lock(vstring_str(data_lock_path), O_RDWR | O_CREAT, 0600, why); set_ugid(getuid(), getgid()); if (data_lock_fp == 0) msg_fatal("open lock file %s: %s", diff --git a/src/master/master_ent.c b/src/master/master_ent.c index 5edc308..98f8404 100644 --- a/src/master/master_ent.c +++ b/src/master/master_ent.c @@ -369,8 +369,12 @@ MASTER_SERV *get_master_ent() } else { MASTER_INET_ADDRLIST(serv) = strcasecmp(saved_interfaces, INET_INTERFACES_ALL) ? - own_inet_addr_list() : /* virtual */ - wildcard_inet_addr_list(); /* wild-card */ + own_inet_addr_list() : /* result can be empty */ + wildcard_inet_addr_list(); /* result can't be empty */ + if (MASTER_INET_ADDRLIST(serv)->used == 0) + fatal_with_context("service definition requires valid" + " host name or address, or non-empty" + " %s setting", VAR_INET_INTERFACES); inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; } diff --git a/src/oqmgr/qmgr_deliver.c b/src/oqmgr/qmgr_deliver.c index 03e0340..6c09350 100644 --- a/src/oqmgr/qmgr_deliver.c +++ b/src/oqmgr/qmgr_deliver.c @@ -155,7 +155,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) */ for (recipient = list.info; recipient < list.info + list.len; recipient++) if (var_smtputf8_enable && (addr = recipient->address)[0] - && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) { + && !allascii(addr) && valid_utf8_stringz(addr)) { smtputf8 |= SMTPUTF8_FLAG_RECIPIENT; if (message->verp_delims) smtputf8 |= SMTPUTF8_FLAG_SENDER; @@ -334,7 +334,7 @@ static void qmgr_deliver_update(int unused_event, void *context) #define SUSPENDED "delivery temporarily suspended: " if (status == DELIVER_STAT_CRASH) - DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error"); + (void) DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error"); if (status == DELIVER_STAT_CRASH || status == DELIVER_STAT_DEFER) { message->flags |= DELIVER_STAT_DEFER; if (VSTRING_LEN(dsb->status)) { diff --git a/src/pipe/pipe.c b/src/pipe/pipe.c index 8a99430..3017937 100644 --- a/src/pipe/pipe.c +++ b/src/pipe/pipe.c @@ -230,6 +230,11 @@ /* This information is modified by the \fBh\fR flag for case folding. /* .sp /* This feature is available as of Postfix 2.5. +/* .IP \fB${envid}\fR +/* This macro expands to the RFC 3461 envelope ID if available, +/* otherwise the empty string. +/* .sp +/* This feature is available as of Postfix 3.9. /* .IP \fB${extension}\fR /* This macro expands to the extension part of a recipient address. /* For example, with an address \fIuser+foo@domain\fR the extension is @@ -544,6 +549,7 @@ #define PIPE_DICT_SASL_USERNAME "sasl_username" /* key */ #define PIPE_DICT_SASL_SENDER "sasl_sender" /* key */ #define PIPE_DICT_QUEUE_ID "queue_id" /* key */ +#define PIPE_DICT_ENVID "envid" /* key */ /* * Flags used to pass back the type of special parameter found by @@ -649,6 +655,7 @@ static int parse_callback(int type, VSTRING *buf, void *context) PIPE_DICT_SASL_USERNAME, 0, PIPE_DICT_SASL_SENDER, 0, PIPE_DICT_QUEUE_ID, 0, + PIPE_DICT_ENVID, 0, 0, 0, }; struct cmd_flags *p; @@ -1278,6 +1285,8 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv) request->sasl_sender); dict_update(PIPE_DICT_TABLE, PIPE_DICT_QUEUE_ID, request->queue_id); + dict_update(PIPE_DICT_TABLE, PIPE_DICT_ENVID, + request->dsn_envid); vstring_free(buf); if ((expanded_argv = expand_argv(service, attr.command, diff --git a/src/postalias/postalias.c b/src/postalias/postalias.c index d17e397..72ca729 100644 --- a/src/postalias/postalias.c +++ b/src/postalias/postalias.c @@ -393,7 +393,7 @@ static void postalias(char *map_type, char *path_name, int postalias_flags, */ if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE) && !allascii(STR(line_buffer)) - && !valid_utf8_string(STR(line_buffer), LEN(line_buffer))) { + && !valid_utf8_stringz(STR(line_buffer))) { msg_warn("%s, line %d: non-UTF-8 input \"%s\"" " -- ignoring this line", VSTREAM_PATH(source_fp), lineno, STR(line_buffer)); diff --git a/src/postcat/postcat.c b/src/postcat/postcat.c index 36f2740..26b46a9 100644 --- a/src/postcat/postcat.c +++ b/src/postcat/postcat.c @@ -76,7 +76,7 @@ /* The default location of the Postfix main.cf and master.cf /* configuration files. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" @@ -274,7 +274,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags) break; /* Optimization: skip to extracted segment marker. */ if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV) - && data_offset >= 0 && data_size >= 0 + && data_offset > 0 && data_size >= 0 && vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0) msg_fatal("seek error: %m"); } @@ -289,7 +289,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags) PRINT_MARKER(flags, fp, offset, rec_type, "MESSAGE CONTENTS"); /* Optimization: skip to extracted segment marker. */ if ((flags & PC_MASK_PRINT_TEXT) == 0 - && data_offset >= 0 && data_size >= 0 + && data_offset > 0 && data_size >= 0 && vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0) msg_fatal("seek error: %m"); /* Update the state machine, even when skipping. */ diff --git a/src/postconf/Makefile.in b/src/postconf/Makefile.in index 6aff794..6df6dfa 100644 --- a/src/postconf/Makefile.in +++ b/src/postconf/Makefile.in @@ -17,7 +17,7 @@ MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \ nint_table.h nint_vars.h nbool_table.h nbool_vars.h long_table.h \ long_vars.h str_fn_table.h str_fn_vars.h DB_MAKES= pcf_ldap_suffixes.h pcf_memcache_suffixes.h pcf_mysql_suffixes.h \ - pcf_pgsql_suffixes.h pcf_sqlite_suffixes.h + pcf_pgsql_suffixes.h pcf_sqlite_suffixes.h pcf_mongodb_suffixes.h TEST_TMP= main.cf master.cf test*.tmp DUMMIES = makes_dummy # for "make -j" PROG = postconf @@ -55,7 +55,8 @@ tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \ test31 test32 test33 test34 test35 test36 test37 test39 test40 test41 \ test42 test43 test44 test45 test46 test47 test48 test49 test50 test51 \ test52 test53 test54 test55 test56 test57 test58 test59 test60 test61 \ - test62 test63 test64 test65 test66 test67 test68 test69 test70 test71 + test62 test63 test64 test65 test66 test67 test68 test69 test70 test71 \ + test72 test73 test74 test75 test76 root_tests: @@ -78,6 +79,9 @@ pcf_ldap_suffixes.h: ../global/dict_ldap.c pcf_memcache_suffixes.h: ../global/dict_memcache.c sh extract_cfg.sh -d ../global/dict_memcache.c > $@ +pcf_mongodb_suffixes.h: ../global/dict_mongodb.c + sh extract_cfg.sh -d ../global/dict_mongodb.c > $@ + pcf_mysql_suffixes.h: ../global/dict_mysql.c sh extract_cfg.sh -d -s ../global/dict_mysql.c > $@ @@ -465,6 +469,9 @@ test29: $(PROG) test29.ref echo 'memcachexx = proxy:memcache:memcachefoo' >> main.cf echo 'memcachefoo_domain = bar' >> main.cf echo 'memcachefoo_domainx = bar' >> main.cf + echo 'mongodbxx = proxy:mongodb:mongodbfoo' >> main.cf + echo 'mongodbfoo_domain = bar' >> main.cf + echo 'mongodbfoo_domainx = bar' >> main.cf touch -t 197101010000 main.cf $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test29.tmp 2>&1 diff test29.ref test29.tmp @@ -807,7 +814,7 @@ test58: $(PROG) test58.ref echo 'yy_backup = bbb' >> main.cf echo 'yy_bogus = bbb' >> main.cf touch -t 197101010000 main.cf - $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./postconf -nc. >test58.tmp 2>&1 || true + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc. >test58.tmp 2>&1 || true diff test58.ref test58.tmp rm -f main.cf master.cf test58.tmp @@ -989,6 +996,75 @@ test71: $(PROG) test71.ref diff test71.ref test71.tmp rm -f main.cf master.cf test71.tmp +# Different requests to add lines to master.cf. +test72: $(PROG) test72.ref + rm -f main.cf master.cf + touch main.cf master.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/unix='smtp unix - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp fifo - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp inet - n n - 0 other' + touch -t 197201010000 main.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. >test72.tmp 2>&1 + diff test72.ref test72.tmp + rm -f main.cf master.cf test72.tmp + +# Replace one entry based on the name+type in the request's service entry. +test73: $(PROG) test73.ref + rm -f main.cf master.cf + touch main.cf master.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/unix='smtp unix - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp fifo - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp inet - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp unix - n n - 0 otherx' + touch -t 197301010000 main.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. >test73.tmp 2>&1 + diff test73.ref test73.tmp + rm -f main.cf master.cf test73.tmp + +# Replace one entry based on the name+type in the request's service pattern. +test74: $(PROG) test74.ref + rm -f main.cf master.cf + touch main.cf master.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/unix='smtp unix - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp fifo - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp inet - n n - 0 other' + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/fifo='lmtp unix - n n - 0 otherx' + touch -t 197401010000 main.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. >test74.tmp 2>&1 + diff test74.ref test74.tmp + rm -f main.cf master.cf test74.tmp + +# Warn about skipping redundant name=value update. +test75: $(PROG) test75.ref + rm -f main.cf master.cf + touch main.cf master.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. mail_version=x mail_version=y >test75.tmp 2>&1 + touch -t 197501010000 main.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc. >>test75.tmp 2>&1 + diff test75.ref test75.tmp + rm -f main.cf master.cf test75.tmp + +# Warn about unused, deprecated, or deleted parameters. +test76: $(PROG) test76.ref + rm -f main.cf master.cf + touch main.cf master.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. \ + config_directory=. \ + deleted-test-only=whatever \ + disable_dns_lookups=no \ + lmtp_use_tls=no \ + smtpd_tls_dh1024_param_file=auto >test76.tmp 2>&1 + touch -t 197601010000 main.cf + echo foo unix - n n - 0 other >> master.cf + echo ' -o alias_maps=foo' >> master.cf + echo ' -o smtp_enforce_tls=yes' >> master.cf + touch -t 197601010000 master.cf + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc. >>test76.tmp 2>&1 + diff test76.ref test76.tmp + $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -qnc. >/dev/null 2>test76.tmp + diff /dev/null test76.tmp + rm -f main.cf master.cf test76.tmp + printfck: $(OBJS) $(PROG) rm -rf printfck mkdir printfck @@ -1094,6 +1170,7 @@ postconf_dbms.o: ../../include/dict.h postconf_dbms.o: ../../include/dict_ht.h postconf_dbms.o: ../../include/dict_ldap.h postconf_dbms.o: ../../include/dict_memcache.h +postconf_dbms.o: ../../include/dict_mongodb.h postconf_dbms.o: ../../include/dict_mysql.h postconf_dbms.o: ../../include/dict_pcre.h postconf_dbms.o: ../../include/dict_pgsql.h @@ -1118,6 +1195,7 @@ postconf_dbms.o: ../../include/vstream.h postconf_dbms.o: ../../include/vstring.h postconf_dbms.o: pcf_ldap_suffixes.h postconf_dbms.o: pcf_memcache_suffixes.h +postconf_dbms.o: pcf_mongodb_suffixes.h postconf_dbms.o: pcf_mysql_suffixes.h postconf_dbms.o: pcf_pgsql_suffixes.h postconf_dbms.o: pcf_sqlite_suffixes.h @@ -1184,6 +1262,7 @@ postconf_main.o: postconf_main.c postconf_master.o: ../../include/argv.h postconf_master.o: ../../include/check_arg.h postconf_master.o: ../../include/dict.h +postconf_master.o: ../../include/dict_ht.h postconf_master.o: ../../include/htable.h postconf_master.o: ../../include/mail_params.h postconf_master.o: ../../include/master_proto.h diff --git a/src/postconf/postconf.c b/src/postconf/postconf.c index f598a5b..74f13b2 100644 --- a/src/postconf/postconf.c +++ b/src/postconf/postconf.c @@ -8,7 +8,7 @@ /* .ti -4 /* \fBManaging main.cf:\fR /* -/* \fBpostconf\fR [\fB-dfhHnopvx\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostconf\fR [\fB-dfhHnopqvx\fR] [\fB-c \fIconfig_dir\fR] /* [\fB-C \fIclass,...\fR] [\fIparameter ...\fR] /* /* \fBpostconf\fR [\fB-epv\fR] [\fB-c \fIconfig_dir\fR] @@ -23,7 +23,7 @@ /* .ti -4 /* \fBManaging master.cf service entries:\fR /* -/* \fBpostconf\fR \fB-M\fR [\fB-fovx\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostconf\fR \fB-M\fR [\fB-foqvx\fR] [\fB-c \fIconfig_dir\fR] /* [\fIservice\fR[\fB/\fItype\fR]\fI ...\fR] /* /* \fBpostconf\fR \fB-M\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] @@ -38,7 +38,7 @@ /* .ti -4 /* \fBManaging master.cf service fields:\fR /* -/* \fBpostconf\fR \fB-F\fR [\fB-fhHovx\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostconf\fR \fB-F\fR [\fB-fhHoqvx\fR] [\fB-c \fIconfig_dir\fR] /* [\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR] /* /* \fBpostconf\fR \fB-F\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] @@ -47,7 +47,7 @@ /* .ti -4 /* \fBManaging master.cf service parameters:\fR /* -/* \fBpostconf\fR \fB-P\fR [\fB-fhHovx\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostconf\fR \fB-P\fR [\fB-fhHoqvx\fR] [\fB-c \fIconfig_dir\fR] /* [\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR] /* /* \fBpostconf\fR \fB-P\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] @@ -293,6 +293,11 @@ /* \fBmemcache_table\fR(5). /* /* This feature is available with Postfix 2.9 and later. +/* .IP "\fBmongodb\fR" +/* MongoDB database client. This is described in +/* \fBmongodb_table\fR(5). +/* +/* This feature is available with Postfix 3.9 and later. /* .IP "\fBmysql\fR (read-only)" /* MySQL database client. Available on systems with support /* for MySQL databases. This is described in \fBmysql_table\fR(5). @@ -452,6 +457,10 @@ /* wildcard fields. /* /* This feature is available with Postfix 2.11 and later. +/* .IP \fB-q\fR +/* Do not log warnings for deprecated or unused parameters. +/* +/* This feature is available with Postfix 3.9 and later. /* .IP "\fB-t\fR [\fItemplate_file\fR]" /* Display the templates for text that appears at the beginning /* of delivery status notification (DSN) messages, without @@ -779,6 +788,8 @@ static void pcf_check_compat_options(int optval) const int (*op)[2]; int excess; + optval &= ~PCF_DEF_MODE; + for (op = pcf_compat_options; op[0][0] != 0; op++) { if ((optval & *op[0]) != 0 && (excess = (optval & ~((*op)[0] | (*op)[1]))) != 0) @@ -844,7 +855,7 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "aAbc:C:deEfFhHlmMno:pPtT:vxX#")) > 0) { + while ((ch = GETOPT(argc, argv, "aAbc:C:deEfFhHlmMno:pPqtT:vxX#")) > 0) { switch (ch) { case 'a': pcf_cmd_mode |= PCF_SHOW_SASL_SERV; @@ -912,6 +923,9 @@ int main(int argc, char **argv) case 'P': pcf_cmd_mode |= PCF_MASTER_PARAM; break; + case 'q': + pcf_cmd_mode &= ~(PCF_WARN_UNUSED_DEPRECATED); + break; case 't': pcf_cmd_mode |= PCF_DUMP_DSN_TEMPL; if (ext_argv) @@ -1028,7 +1042,7 @@ int main(int argc, char **argv) pcf_set_parameters(override_params->argv); pcf_register_builtin_parameters(basename(argv[0]), getpid()); pcf_register_service_parameters(); - pcf_register_user_parameters(); + pcf_register_user_parameters(pcf_cmd_mode); if (pcf_cmd_mode & PCF_MASTER_FLD) pcf_show_master_fields(VSTREAM_OUT, pcf_cmd_mode, argc - optind, argv + optind); @@ -1038,7 +1052,8 @@ int main(int argc, char **argv) else pcf_show_master_entries(VSTREAM_OUT, pcf_cmd_mode, argc - optind, argv + optind); - pcf_flag_unused_master_parameters(); + if (pcf_cmd_mode & PCF_WARN_UNUSED_DEPRECATED) + pcf_flag_unused_master_parameters(); } /* @@ -1090,7 +1105,7 @@ int main(int argc, char **argv) pcf_read_master(PCF_WARN_ON_OPEN_ERROR); pcf_register_service_parameters(); if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0) - pcf_register_user_parameters(); + pcf_register_user_parameters(pcf_cmd_mode); /* * Show the requested values. @@ -1099,11 +1114,12 @@ int main(int argc, char **argv) argv + optind); /* - * Flag unused parameters. This makes no sense with "postconf -d", - * because that ignores all the user-specified parameters and - * user-specified macro expansions in main.cf. + * Flag unused or deprecated parameters. This makes no sense with + * "postconf -d", because that ignores all the user-specified + * parameters and user-specified macro expansions in main.cf. */ - if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0) { + if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0 + && (pcf_cmd_mode & PCF_WARN_UNUSED_DEPRECATED) != 0) { pcf_flag_unused_main_parameters(); pcf_flag_unused_master_parameters(); } diff --git a/src/postconf/postconf.h b/src/postconf/postconf.h index 24a1ed7..b42245c 100644 --- a/src/postconf/postconf.h +++ b/src/postconf/postconf.h @@ -46,8 +46,9 @@ #define PCF_MASTER_PARAM (1<<19) /* manage master.cf -o name=value */ #define PCF_HIDE_VALUE (1<<20) /* hide main.cf/master.cf =value */ #define PCF_SHOW_TLS (1<<21) /* TLS support introspection */ +#define PCF_WARN_UNUSED_DEPRECATED (1<<22) /* As the name says */ -#define PCF_DEF_MODE 0 +#define PCF_DEF_MODE (PCF_WARN_UNUSED_DEPRECATED) /* * Structure for one "valid parameter" (built-in, service-defined or valid @@ -274,12 +275,12 @@ typedef struct { /* * postconf_user.c. */ -extern void pcf_register_user_parameters(void); +extern void pcf_register_user_parameters(int); /* * postconf_dbms.c */ -extern void pcf_register_dbms_parameters(const char *, +extern void pcf_register_dbms_parameters(int, const char *, const char *(*) (const char *, int, PCF_MASTER_ENT *), PCF_MASTER_ENT *); diff --git a/src/postconf/postconf_dbms.c b/src/postconf/postconf_dbms.c index 0ed5b53..105ae85 100644 --- a/src/postconf/postconf_dbms.c +++ b/src/postconf/postconf_dbms.c @@ -6,8 +6,9 @@ /* SYNOPSIS /* #include /* -/* void pcf_register_dbms_parameters(param_value, flag_parameter, +/* void pcf_register_dbms_parameters(mode, param_value, flag_parameter, /* local_scope) +/* int mode; /* const char *param_value; /* const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *); /* PCF_MASTER_ENT *local_scope; @@ -17,6 +18,9 @@ /* the database name to a database-defined suffix. /* /* Arguments: +/* .IP mode +/* If PCF_WARN_UNUSED_DEPRECATED is set, warn about unused +/* database settings. /* .IP param_value /* A parameter value to be searched for "type:table" strings. /* When a database type is found that supports legacy-style @@ -77,6 +81,7 @@ #include #include #include +#include #include #include @@ -131,6 +136,13 @@ static const char *pcf_memcache_suffixes[] = { 0, }; +/* See mongodb_table(5). */ + +static const char *pcf_mongodb_suffixes[] = { +#include "pcf_mongodb_suffixes.h" + 0, +}; + /* * Bundle up the database types and their suffix lists. */ @@ -149,6 +161,7 @@ static const PCF_DBMS_INFO pcf_dbms_info[] = { {DICT_TYPE_PGSQL, PCF_DBMS_CLASS_CLIENT, pcf_pgsql_suffixes}, {DICT_TYPE_SQLITE, PCF_DBMS_CLASS_CLIENT, pcf_sqlite_suffixes}, {DICT_TYPE_MEMCACHE, PCF_DBMS_CLASS_CLIENT, pcf_memcache_suffixes}, + {DICT_TYPE_MONGODB, PCF_DBMS_CLASS_CLIENT, pcf_mongodb_suffixes}, {DICT_TYPE_REGEXP, PCF_DBMS_CLASS_REGEX}, {DICT_TYPE_PCRE, PCF_DBMS_CLASS_REGEX}, {0}, @@ -163,7 +176,8 @@ static const PCF_DBMS_INFO pcf_dbms_info[] = { /* pcf_check_dbms_client - look for unused names in client configuration */ -static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file) +static void pcf_check_dbms_client(int mode, const PCF_DBMS_INFO *dp, + const char *cf_file) { DICT *dict; VSTREAM *fp; @@ -217,19 +231,21 @@ static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file) * code, because a database client parameter namespace is unlike the * parameter namespaces in main.cf or master.cf. */ - for (cpp = dp->db_suffixes; *cpp; cpp++) - (void) dict_del(dict, *cpp); - for (dir = DICT_SEQ_FUN_FIRST; - dict->sequence(dict, dir, &name, &value) == DICT_STAT_SUCCESS; - dir = DICT_SEQ_FUN_NEXT) - msg_warn("%s: unused parameter: %s=%s", dict_spec, name, value); + if (mode & PCF_WARN_UNUSED_DEPRECATED) { + for (cpp = dp->db_suffixes; *cpp; cpp++) + (void) dict_del(dict, *cpp); + for (dir = DICT_SEQ_FUN_FIRST; + dict->sequence(dict, dir, &name, &value) == DICT_STAT_SUCCESS; + dir = DICT_SEQ_FUN_NEXT) + msg_warn("%s: unused parameter: %s=%s", dict_spec, name, value); + } } myfree(dict_spec); } /* pcf_register_dbms_helper - parse one possible database type:name */ -static void pcf_register_dbms_helper(char *str_value, +static void pcf_register_dbms_helper(int mode, char *str_value, const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *), PCF_MASTER_ENT *local_scope, int recurse) @@ -258,8 +274,8 @@ static void pcf_register_dbms_helper(char *str_value, myfree(err); } if (recurse) - pcf_register_dbms_helper(db_type, flag_parameter, local_scope, - recurse); + pcf_register_dbms_helper(mode, db_type, flag_parameter, + local_scope, recurse); continue; } @@ -287,7 +303,7 @@ static void pcf_register_dbms_helper(char *str_value, for (dp = pcf_dbms_info; dp->db_type != 0; dp++) { if (strcmp(db_type, dp->db_type) == 0) { if (dp->db_class == PCF_DBMS_CLASS_CLIENT) - pcf_check_dbms_client(dp, prefix); + pcf_check_dbms_client(mode, dp, prefix); break; } } @@ -321,8 +337,8 @@ static void pcf_register_dbms_helper(char *str_value, break; } } - pcf_register_dbms_helper(prefix, flag_parameter, local_scope, - next_recurse); + pcf_register_dbms_helper(mode, prefix, flag_parameter, + local_scope, next_recurse); continue; } else { for (dp = pcf_dbms_info; dp->db_type != 0; dp++) { @@ -347,7 +363,7 @@ static void pcf_register_dbms_helper(char *str_value, /* pcf_register_dbms_parameters - look for database_type:prefix_name */ -void pcf_register_dbms_parameters(const char *param_value, +void pcf_register_dbms_parameters(int mode, const char *param_value, const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *), PCF_MASTER_ENT *local_scope) { @@ -363,7 +379,8 @@ void pcf_register_dbms_parameters(const char *param_value, buffer = vstring_alloc(100); bufp = pcf_expand_parameter_value(buffer, PCF_SHOW_EVAL, param_value, local_scope); - pcf_register_dbms_helper(bufp, flag_parameter, local_scope, PCF_DBMS_RECURSE); + pcf_register_dbms_helper(mode, bufp, flag_parameter, local_scope, + PCF_DBMS_RECURSE); } #endif diff --git a/src/postconf/postconf_unused.c b/src/postconf/postconf_unused.c index d4416f8..717d1a5 100644 --- a/src/postconf/postconf_unused.c +++ b/src/postconf/postconf_unused.c @@ -2,7 +2,7 @@ /* NAME /* postconf_unused 3 /* SUMMARY -/* report unused parameters +/* report unused or deprecated parameters /* SYNOPSIS /* #include /* @@ -15,11 +15,11 @@ /* In other words, don't call these functions with "postconf /* -d" which ignores user-defined main.cf settings. /* -/* pcf_flag_unused_main_parameters() reports unused "name=value" -/* entries in main.cf. +/* pcf_flag_unused_main_parameters() reports unused or deprecated +/* "name=value" entries in main.cf. /* -/* pcf_flag_unused_master_parameters() reports unused "-o -/* name=value" entries in master.cf. +/* pcf_flag_unused_master_parameters() reports unused or +/* deprecated "-o name=value" entries in master.cf. /* DIAGNOSTICS /* Problems are reported to the standard error stream. /* LICENSE @@ -31,6 +31,10 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA /*--*/ /* System library. */ @@ -52,12 +56,66 @@ #include + /* + * Deprecated parameter names and suggested alternatives. If we keep deleted + * parameter names in the table, a warning can still suggest alternatives. + * The downside of keeping deleted names in the table is that we may falsely + * warn about a user-defined parameter whose name matches that of a deleted + * parameter. + */ +typedef struct { + char *name; + char *alternative; +} PCF_DEPR_PARAM_INFO; + +static const PCF_DEPR_PARAM_INFO pcf_depr_param_info[] = { + + /* + * Parameters with deprecation warnings as of Postfix 3.9. The + * disable_dns_lookups parameter was documented as deprecated since + * Postfix 2.11 but nothing was logged. + */ + "disable_dns_lookups", "specify \"smtp_dns_support_level\"", + "lmtp_use_tls", "specify \"lmtp_tls_security_level\"", + "postscreen_use_tls", "specify \"postscreen_tls_security_level\"", + "smtp_use_tls", "specify \"smtp_tls_security_level\"", + "smtpd_use_tls", "specify \"smtpd_tls_security_level\"", + "tlsproxy_client_use_tls", "specify \"tlsproxy_client_security_level\"", + "tlsproxy_use_tls", "specify \"tlsproxy_tls_security_level\"", + "lmtp_enforce_tls", "lmtp_tls_security_level", + "postscreen_enforce_tls", "specify \"postscreen_tls_security_level\"", + "smtp_enforce_tls", "specify \"smtp_tls_security_level\"", + "smtpd_enforce_tls", "specify \"smtpd_tls_security_level\"", + "tlsproxy_client_enforce_tls", "specify \"tlsproxy_client_security_level\"", + "tlsproxy_enforce_tls", "specify \"tlsproxy_tls_security_level\"", + "lmtp_tls_per_site", "specify \"lmtp_tls_policy_maps\"", + "smtp_tls_per_site", "specify \"smtp_tls_policy_maps\"", + "tlsproxy_client_per_site", "specify \"tlsproxy_client_policy_maps\"", + "smtpd_tls_dh1024_param_file", "do not specify (leave at default)", + "smtpd_tls_eecdh_grade", "do not specify (leave at default)", + "deleted-test-only", "do not specify", /* For testing */ + 0, +}; +static HTABLE *pcf_depr_param_table; + +/* pcf_init_depr_params - initialize lookup table */ + +static void pcf_init_depr_params(void) +{ + const PCF_DEPR_PARAM_INFO *dp; + + pcf_depr_param_table = htable_create(30); + for (dp = pcf_depr_param_info; dp->name; dp++) + (void) htable_enter(pcf_depr_param_table, dp->name, (void *) dp); +} + /* pcf_flag_unused_parameters - warn about unused parameters */ static void pcf_flag_unused_parameters(DICT *dict, const char *conf_name, PCF_MASTER_ENT *local_scope) { const char *myname = "pcf_flag_unused_parameters"; + const PCF_DEPR_PARAM_INFO *dp; const char *param_name; const char *param_value; int how; @@ -67,23 +125,55 @@ static void pcf_flag_unused_parameters(DICT *dict, const char *conf_name, */ if (pcf_param_table == 0) msg_panic("%s: global parameter table is not initialized", myname); + if (dict->sequence == 0) + msg_panic("%s: parameter dictionary %s has no iterator", + myname, conf_name); + + /* + * One-time initialization. + */ + if (pcf_depr_param_table == 0) + pcf_init_depr_params(); /* * Iterate over all entries, and flag parameter names that aren't used - * anywhere. Show the warning message at the end of the output. + * anywhere, or that are deprecated. Show the warning message(s) after + * the end of the stdout output. */ - if (dict->sequence == 0) - msg_panic("%s: parameter dictionary %s has no iterator", - myname, conf_name); for (how = DICT_SEQ_FUN_FIRST; dict->sequence(dict, how, ¶m_name, ¶m_value) == 0; how = DICT_SEQ_FUN_NEXT) { + + /* + * Flag a parameter that is not used (deleted name, or incorrect + * name). + */ if (PCF_PARAM_TABLE_LOCATE(pcf_param_table, param_name) == 0 && (local_scope == 0 || PCF_PARAM_TABLE_LOCATE(local_scope->valid_names, param_name) == 0)) { vstream_fflush(VSTREAM_OUT); - msg_warn("%s/%s: unused parameter: %s=%s", - var_config_dir, conf_name, param_name, param_value); + if ((dp = (const PCF_DEPR_PARAM_INFO *) + htable_find(pcf_depr_param_table, param_name)) != 0) { + msg_warn("%s/%s: support for parameter %s has been removed;" + " instead, %s", var_config_dir, conf_name, + param_name, dp->alternative); + } else { + msg_warn("%s/%s: unused parameter: %s=%s", + var_config_dir, conf_name, param_name, param_value); + } + } + + /* + * Flag a parameter that is used but deprecated. Note that this may + * falsely complain about a user-defined parameter whose name matches + * that of a deleted parameter. + */ + else if ((dp = (const PCF_DEPR_PARAM_INFO *) + htable_find(pcf_depr_param_table, param_name)) != 0) { + vstream_fflush(VSTREAM_OUT); + msg_warn("%s/%s: support for parameter \"%s\" will be removed;" + " instead, %s", var_config_dir, conf_name, + param_name, dp->alternative); } } } diff --git a/src/postconf/postconf_user.c b/src/postconf/postconf_user.c index 5942ec0..46f4d61 100644 --- a/src/postconf/postconf_user.c +++ b/src/postconf/postconf_user.c @@ -6,7 +6,7 @@ /* SYNOPSIS /* #include /* -/* void pcf_register_user_parameters() +/* void pcf_register_user_parameters(int mode) /* DESCRIPTION /* Postfix has multiple parameter name spaces: the global /* main.cf parameter name space, and the local parameter name @@ -40,6 +40,10 @@ /* to instantiate legacy per-dbms parameters, and to examine /* per-dbms configuration files. This is limited to the content /* of global and local, built-in and per-service, parameters. +/* +/* Arguments: +/* .IP mode +/* Passed on to pcf_register_dbms_parameters(). /* DIAGNOSTICS /* Problems are reported to the standard error stream. /* LICENSE @@ -224,7 +228,7 @@ static const char *pcf_lookup_eval(const char *dict_name, const char *name) /* pcf_scan_user_parameter_namespace - scan parameters in name space */ -static void pcf_scan_user_parameter_namespace(const char *dict_name, +static void pcf_scan_user_parameter_namespace(int mode, const char *dict_name, PCF_MASTER_ENT *local_scope) { const char *myname = "pcf_scan_user_parameter_namespace"; @@ -308,7 +312,7 @@ static void pcf_scan_user_parameter_namespace(const char *dict_name, */ if (node != 0 && (PCF_BUILTIN_PARAMETER(node) || PCF_SERVICE_PARAMETER(node))) - pcf_register_dbms_parameters(cparam_value, pcf_flag_user_parameter, + pcf_register_dbms_parameters(mode, cparam_value, pcf_flag_user_parameter, local_scope); #endif } @@ -345,7 +349,7 @@ static void pcf_scan_default_parameter_values(HTABLE *valid_params, /* pcf_register_user_parameters - add parameters with user-defined names */ -void pcf_register_user_parameters(void) +void pcf_register_user_parameters(int mode) { const char *myname = "pcf_register_user_parameters"; PCF_MASTER_ENT *masterp; @@ -403,7 +407,7 @@ void pcf_register_user_parameters(void) */ for (masterp = pcf_master_table; masterp->argv != 0; masterp++) if (masterp->all_params != 0) - pcf_scan_user_parameter_namespace(masterp->name_space, masterp); + pcf_scan_user_parameter_namespace(mode, masterp->name_space, masterp); /* * Scan parameter values that are left at their defaults in the global @@ -418,5 +422,5 @@ void pcf_register_user_parameters(void) /* * Scan the explicit name=value entries in the global name space. */ - pcf_scan_user_parameter_namespace(CONFIG_DICT, (PCF_MASTER_ENT *) 0); + pcf_scan_user_parameter_namespace(mode, CONFIG_DICT, (PCF_MASTER_ENT *) 0); } diff --git a/src/postconf/test29.ref b/src/postconf/test29.ref index 646890a..c3bbaec 100644 --- a/src/postconf/test29.ref +++ b/src/postconf/test29.ref @@ -2,15 +2,18 @@ config_directory = . ./postconf: warning: ./main.cf: unused parameter: pgsqlfoo_domain=bar ./postconf: warning: ./main.cf: unused parameter: sqlitefoo_domain=bar ./postconf: warning: ./main.cf: unused parameter: ldapxx=proxy:ldap:ldapfoo +./postconf: warning: ./main.cf: unused parameter: mongodbfoo_domain=bar ./postconf: warning: ./main.cf: unused parameter: sqlitexx=proxy:sqlite:sqlitefoo ./postconf: warning: ./main.cf: unused parameter: mysqlfoo_domain=bar ./postconf: warning: ./main.cf: unused parameter: sqlitefoo_domainx=bar ./postconf: warning: ./main.cf: unused parameter: memcachefoo_domain=bar ./postconf: warning: ./main.cf: unused parameter: pgsqlfoo_domainx=bar +./postconf: warning: ./main.cf: unused parameter: mongodbfoo_domainx=bar ./postconf: warning: ./main.cf: unused parameter: ldapfoo_domainx=bar ./postconf: warning: ./main.cf: unused parameter: ldapfoo_domain=bar ./postconf: warning: ./main.cf: unused parameter: memcachexx=proxy:memcache:memcachefoo ./postconf: warning: ./main.cf: unused parameter: memcachefoo_domainx=bar ./postconf: warning: ./main.cf: unused parameter: mysqlfoo_domainx=bar ./postconf: warning: ./main.cf: unused parameter: mysqlxx=proxy:mysql:mysqlfoo +./postconf: warning: ./main.cf: unused parameter: mongodbxx=proxy:mongodb:mongodbfoo ./postconf: warning: ./main.cf: unused parameter: pgsqlxx=proxy:pgsql:pgsqlfoo diff --git a/src/postconf/test72.ref b/src/postconf/test72.ref new file mode 100644 index 0000000..6b13cdc --- /dev/null +++ b/src/postconf/test72.ref @@ -0,0 +1,3 @@ +smtp unix - n n - 0 other +smtp fifo - n n - 0 other +smtp inet - n n - 0 other diff --git a/src/postconf/test73.ref b/src/postconf/test73.ref new file mode 100644 index 0000000..9554cc0 --- /dev/null +++ b/src/postconf/test73.ref @@ -0,0 +1,3 @@ +smtp unix - n n - 0 otherx +smtp fifo - n n - 0 other +smtp inet - n n - 0 other diff --git a/src/postconf/test74.ref b/src/postconf/test74.ref new file mode 100644 index 0000000..2886334 --- /dev/null +++ b/src/postconf/test74.ref @@ -0,0 +1,3 @@ +smtp unix - n n - 0 other +lmtp unix - n n - 0 otherx +smtp inet - n n - 0 other diff --git a/src/postconf/test75.ref b/src/postconf/test75.ref new file mode 100644 index 0000000..b8c54ab --- /dev/null +++ b/src/postconf/test75.ref @@ -0,0 +1,3 @@ +./postconf: warning: ignoring earlier request: 'mail_version = x' +config_directory = . +mail_version = y diff --git a/src/postconf/test76.ref b/src/postconf/test76.ref new file mode 100644 index 0000000..3e4cd26 --- /dev/null +++ b/src/postconf/test76.ref @@ -0,0 +1,9 @@ +config_directory = . +disable_dns_lookups = no +lmtp_use_tls = no +smtpd_tls_dh1024_param_file = auto +./postconf: warning: ./main.cf: support for parameter "disable_dns_lookups" will be removed; instead, specify "smtp_dns_support_level" +./postconf: warning: ./main.cf: support for parameter "lmtp_use_tls" will be removed; instead, specify "lmtp_tls_security_level" +./postconf: warning: ./main.cf: support for parameter "smtpd_tls_dh1024_param_file" will be removed; instead, do not specify (leave at default) +./postconf: warning: ./main.cf: support for parameter deleted-test-only has been removed; instead, do not specify +./postconf: warning: ./master.cf: support for parameter "smtp_enforce_tls" will be removed; instead, specify "smtp_tls_security_level" diff --git a/src/postdrop/postdrop.c b/src/postdrop/postdrop.c index e9335e9..66c9ea5 100644 --- a/src/postdrop/postdrop.c +++ b/src/postdrop/postdrop.c @@ -64,7 +64,7 @@ /* The default location of the Postfix main.cf and master.cf /* configuration files. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/src/postfix/postfix.c b/src/postfix/postfix.c index c7f8b40..93bcecc 100644 --- a/src/postfix/postfix.c +++ b/src/postfix/postfix.c @@ -303,7 +303,7 @@ /* /* Table-driven mechanisms: /* access(5), Postfix SMTP access control table -/* aliases(5), Postfix alias database +/* aliases(5), Postfix local aliasing /* canonical(5), Postfix input address rewriting /* generic(5), Postfix output address rewriting /* header_checks(5), body_checks(5), Postfix content inspection @@ -316,6 +316,7 @@ /* ldap_table(5), Postfix LDAP client /* lmdb_table(5), Postfix LMDB database driver /* memcache_table(5), Postfix memcache client +/* mongodb_table(5), Postfix MongoDB client /* mysql_table(5), Postfix MYSQL client /* nisplus_table(5), Postfix NIS+ client /* pcre_table(5), Associate PCRE pattern with value diff --git a/src/postkick/postkick.c b/src/postkick/postkick.c index 6bf9245..a1ce55c 100644 --- a/src/postkick/postkick.c +++ b/src/postkick/postkick.c @@ -54,7 +54,7 @@ /* How long the \fBpostkick\fR(1) command waits for a request to enter the /* Postfix daemon process input buffer before giving up. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/src/postlock/postlock.c b/src/postlock/postlock.c index a05d11e..972577b 100644 --- a/src/postlock/postlock.c +++ b/src/postlock/postlock.c @@ -79,7 +79,7 @@ /* The default location of the Postfix main.cf and master.cf /* configuration files. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* SEE ALSO diff --git a/src/postlog/postlog.c b/src/postlog/postlog.c index 7175f42..195ebd9 100644 --- a/src/postlog/postlog.c +++ b/src/postlog/postlog.c @@ -82,6 +82,12 @@ /* \fBpostlogd\fR(8) service. /* .IP "\fBpostlog_service_name (postlog)\fR" /* The name of the \fBpostlogd\fR(8) service entry in master.cf. +/* .PP +/* Available in Postfix 3.9 and later: +/* .IP "\fBmaillog_file_permissions (0600)\fR" +/* The file access permissions that will be set when the file +/* $maillog_file is created for the first time, or when the file is +/* created after an existing file is rotated. /* SEE ALSO /* postconf(5), configuration parameters /* postlogd(8), Postfix logging diff --git a/src/postlogd/postlogd.c b/src/postlogd/postlogd.c index 902cbe5..13f996f 100644 --- a/src/postlogd/postlogd.c +++ b/src/postlogd/postlogd.c @@ -31,10 +31,10 @@ /* CONFIGURATION PARAMETERS /* .ad /* .fi -/* Changes to \fBmain.cf\fR are picked up automatically, as -/* \fBpostlogd\fR(8) processes run for only a limited amount -/* of time. Use the command "\fBpostfix reload\fR" to speed -/* up a change. +/* Changes to \fBmain.cf\fR are not picked up automatically, +/* because \fBpostlogd\fR(8) terminates only after reaching +/* the \fBmax_idle\fR time limit. +/* Use the command "\fBpostfix reload\fR" to speed up a change. /* /* The text below provides only a parameter summary. See /* \fBpostconf\fR(5) for more details including examples. @@ -56,6 +56,12 @@ /* .IP "\fBpostlogd_watchdog_timeout (10s)\fR" /* How much time a \fBpostlogd\fR(8) process may take to process a request /* before it is terminated by a built-in watchdog timer. +/* .PP +/* Available in Postfix 3.9 and later: +/* .IP "\fBmaillog_file_permissions (0600)\fR" +/* The file access permissions that will be set when the file +/* $maillog_file is created for the first time, or when the file is +/* created after an existing file is rotated. /* SEE ALSO /* postconf(5), configuration parameters /* syslogd(8), system logging diff --git a/src/postmap/postmap.c b/src/postmap/postmap.c index 2826fc6..7390450 100644 --- a/src/postmap/postmap.c +++ b/src/postmap/postmap.c @@ -489,7 +489,7 @@ static void postmap(char *map_type, char *path_name, int postmap_flags, */ if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE) && !allascii(STR(line_buffer)) - && !valid_utf8_string(STR(line_buffer), LEN(line_buffer))) { + && !valid_utf8_stringz(STR(line_buffer))) { msg_warn("%s, line %d: non-UTF-8 input \"%s\"" " -- ignoring this line", VSTREAM_PATH(source_fp), lineno, STR(line_buffer)); diff --git a/src/postqueue/showq_json.c b/src/postqueue/showq_json.c index db79404..a2820dd 100644 --- a/src/postqueue/showq_json.c +++ b/src/postqueue/showq_json.c @@ -58,69 +58,6 @@ #define STR(x) vstring_str(x) #define LEN(x) VSTRING_LEN(x) -/* json_quote - quote JSON string */ - -static char *json_quote(VSTRING *result, const char *text) -{ - unsigned char *cp; - int ch; - - /* - * We use short escape sequences for common control characters. Note that - * RFC 4627 allows "/" (0x2F) to be sent without quoting. Differences - * with RFC 4627: we send DEL (0x7f) as \u007F; the result remains RFC - * 4627 complaint. - */ - VSTRING_RESET(result); - for (cp = (unsigned char *) text; (ch = *cp) != 0; cp++) { - if (UNEXPECTED(ISCNTRL(ch))) { - switch (ch) { - case '\b': - VSTRING_ADDCH(result, '\\'); - VSTRING_ADDCH(result, 'b'); - break; - case '\f': - VSTRING_ADDCH(result, '\\'); - VSTRING_ADDCH(result, 'f'); - break; - case '\n': - VSTRING_ADDCH(result, '\\'); - VSTRING_ADDCH(result, 'n'); - break; - case '\r': - VSTRING_ADDCH(result, '\\'); - VSTRING_ADDCH(result, 'r'); - break; - case '\t': - VSTRING_ADDCH(result, '\\'); - VSTRING_ADDCH(result, 't'); - break; - default: - vstring_sprintf_append(result, "\\u%04X", ch); - break; - } - } else { - switch (ch) { - case '\\': - case '"': - VSTRING_ADDCH(result, '\\'); - /* FALLTHROUGH */ - default: - VSTRING_ADDCH(result, ch); - break; - } - } - } - VSTRING_TERMINATE(result); - - /* - * Force the result to be UTF-8 (with SMTPUTF8 enabled) or ASCII (with - * SMTPUTF8 disabled). - */ - printable(STR(result), '?'); - return (STR(result)); -} - /* json_message - report status for one message */ static void format_json(VSTREAM *showq_stream) @@ -147,6 +84,12 @@ static void format_json(VSTREAM *showq_stream) quote_buf = vstring_alloc(100); } + /* + * Force JSON values to UTF-8 (with SMTPUTF8 enabled) or ASCII (with + * SMTPUTF8 disabled). + */ +#define QUOTE_JSON(res, src) printable(quote_for_json((res), (src), -1), '?') + /* * Read the message properties and sender address. */ @@ -162,14 +105,14 @@ static void format_json(VSTREAM *showq_stream) msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); vstream_printf("{"); vstream_printf("\"queue_name\": \"%s\", ", - json_quote(quote_buf, STR(queue_name))); + QUOTE_JSON(quote_buf, STR(queue_name))); vstream_printf("\"queue_id\": \"%s\", ", - json_quote(quote_buf, STR(queue_id))); + QUOTE_JSON(quote_buf, STR(queue_id))); vstream_printf("\"arrival_time\": %ld, ", arrival_time); vstream_printf("\"message_size\": %ld, ", message_size); vstream_printf("\"forced_expire\": %s, ", forced_expire ? "true" : "false"); vstream_printf("\"sender\": \"%s\", ", - json_quote(quote_buf, STR(addr))); + QUOTE_JSON(quote_buf, STR(addr))); /* * Read zero or more (recipient, reason) pair(s) until attr_scan_more() @@ -188,10 +131,10 @@ static void format_json(VSTREAM *showq_stream) ATTR_TYPE_END) != 2) msg_fatal_status(EX_SOFTWARE, "malformed showq server response"); vstream_printf("\"address\": \"%s\"", - json_quote(quote_buf, STR(addr))); + QUOTE_JSON(quote_buf, STR(addr))); if (LEN(why) > 0) vstream_printf(", \"delay_reason\": \"%s\"", - json_quote(quote_buf, STR(why))); + QUOTE_JSON(quote_buf, STR(why))); vstream_printf("}"); } vstream_printf("]"); diff --git a/src/postscreen/postscreen.c b/src/postscreen/postscreen.c index 192c2e9..ebb680c 100644 --- a/src/postscreen/postscreen.c +++ b/src/postscreen/postscreen.c @@ -291,25 +291,29 @@ /* The amount of time that \fBpostscreen\fR(8) will cache an expired /* temporary allowlist entry before it is removed. /* .IP "\fBpostscreen_bare_newline_ttl (30d)\fR" -/* The amount of time that \fBpostscreen\fR(8) will use the result from -/* a successful "bare newline" SMTP protocol test. +/* The amount of time that \fBpostscreen\fR(8) remembers that a client +/* IP address passed a "bare newline" SMTP protocol test, before it +/* address is required to pass that test again. /* .IP "\fBpostscreen_dnsbl_max_ttl (${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)\fR" -/* The maximum amount of time that \fBpostscreen\fR(8) will use the -/* result from a successful DNS-based reputation test before a -/* client IP address is required to pass that test again. +/* The maximum amount of time that \fBpostscreen\fR(8) remembers that a +/* client IP address passed a DNS-based reputation test, before it is +/* required to pass that test again. /* .IP "\fBpostscreen_dnsbl_min_ttl (60s)\fR" -/* The minimum amount of time that \fBpostscreen\fR(8) will use the -/* result from a successful DNS-based reputation test before a -/* client IP address is required to pass that test again. +/* The minimum amount of time that \fBpostscreen\fR(8) remembers that a +/* client IP address passed a DNS-based reputation test, before it +/* is required to pass that test again. /* .IP "\fBpostscreen_greet_ttl (1d)\fR" -/* The amount of time that \fBpostscreen\fR(8) will use the result from -/* a successful PREGREET test. +/* The amount of time that \fBpostscreen\fR(8) remembers that a client +/* IP address passed a PREGREET test, before it is required to pass +/* that test again. /* .IP "\fBpostscreen_non_smtp_command_ttl (30d)\fR" -/* The amount of time that \fBpostscreen\fR(8) will use the result from -/* a successful "non_smtp_command" SMTP protocol test. +/* The amount of time that \fBpostscreen\fR(8) remembers that a client +/* IP address passed a "non_smtp_command" SMTP protocol test, before +/* it is required to pass that test again. /* .IP "\fBpostscreen_pipelining_ttl (30d)\fR" -/* The amount of time that \fBpostscreen\fR(8) will use the result from -/* a successful "pipelining" SMTP protocol test. +/* The amount of time that \fBpostscreen\fR(8) remembers that a client +/* IP address passed a "pipelining" SMTP protocol test, before it is +/* required to pass that test again. /* RESOURCE CONTROLS /* .ad /* .fi diff --git a/src/postscreen/postscreen_smtpd.c b/src/postscreen/postscreen_smtpd.c index dfc5d54..6b72626 100644 --- a/src/postscreen/postscreen_smtpd.c +++ b/src/postscreen/postscreen_smtpd.c @@ -874,7 +874,8 @@ static void psc_smtpd_read_event(int event, void *context) } /* - * Bare newline test. + * Bare newline test. Note: at this point, state->cmd_buffer is + * not null-terminated and may contain embedded null bytes. */ if (ch == '\n') { if ((state->flags & PSC_STATE_MASK_BARLF_TODO_SKIP) @@ -929,18 +930,19 @@ static void psc_smtpd_read_event(int event, void *context) } /* - * Avoid complaints from Postfix maps about malformed content. + * Avoid complaints from Postfix maps about malformed content. Note: + * this will stop at the first null byte, just like the code that + * parses the command name or command arguments. */ -#define PSC_BAD_UTF8(str, len) \ - (var_smtputf8_enable && !valid_utf8_string((str), (len))) +#define PSC_BAD_UTF8(str) \ + (var_smtputf8_enable && !valid_utf8_stringz(str)) /* * Terminate the command buffer, and apply the last-resort command * editing workaround. */ VSTRING_TERMINATE(state->cmd_buffer); - if (psc_cmd_filter != 0 && !PSC_BAD_UTF8(STR(state->cmd_buffer), - LEN(state->cmd_buffer))) { + if (psc_cmd_filter != 0 && !PSC_BAD_UTF8(STR(state->cmd_buffer))) { const char *cp; for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++) @@ -1007,7 +1009,7 @@ static void psc_smtpd_read_event(int event, void *context) if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_SKIP) == PSC_STATE_FLAG_NSMTP_TODO && cmdp->name == 0 && (is_header(command) - || PSC_BAD_UTF8(command, strlen(command)) + || PSC_BAD_UTF8(command) /* Ignore forbid_cmds lookup errors. Non-critical feature. */ || (*var_psc_forbid_cmds && string_list_match(psc_forbid_cmds, command)))) { diff --git a/src/postsuper/postsuper.c b/src/postsuper/postsuper.c index d3f2d5b..c9b8e38 100644 --- a/src/postsuper/postsuper.c +++ b/src/postsuper/postsuper.c @@ -288,7 +288,7 @@ /* The names of queue directories that are split across multiple /* subdirectory levels. /* .IP "\fBimport_environment (see 'postconf -d' output)\fR" -/* The list of environment parameters that a privileged Postfix +/* The list of environment variables that a privileged Postfix /* process will import from a non-Postfix parent process, or name=value /* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" diff --git a/src/posttls-finger/posttls-finger.c b/src/posttls-finger/posttls-finger.c index d64c355..b474a40 100644 --- a/src/posttls-finger/posttls-finger.c +++ b/src/posttls-finger/posttls-finger.c @@ -103,7 +103,7 @@ /* in the DNS). In Postfix versions prior to 3.6, the default value /* was "md5". /* .IP "\fB-f\fR" -/* Lookup the associated DANE TLSA RRset even when a hostname is not an +/* Look up the associated DANE TLSA RRset even when a hostname is not an /* alias and its address records lie in an unsigned zone. See /* smtp_tls_force_insecure_host_tlsa_lookup for details. /* .IP "\fB-F \fICAfile.pem\fR (default: none)" @@ -264,6 +264,15 @@ /* the SMTP-in-SSL protocol, rather than the STARTTLS protocol. /* The destination \fIdomain\fR:\fIport\fR must of course provide such /* a service. +/* .IP "\fB-x\fR" +/* Prefer RFC7250 non-X.509 raw public key (RPK) server credentials. By +/* default only X.509 certificates are accepted. This is analogous to +/* setting \fBsmtp_tls_enable_rpk = yes\fR in the smtp(8) client. At the +/* fingerprint security level, when raw public keys are enabled, only +/* public key (and not certificate) fingerprints will be compared against +/* the specified list of \fImatch\fR arguments. Certificate fingerprints +/* are fragile when raw public keys are solicited, the server may at some +/* point in time start returning only the public key. /* .IP "\fB-X\fR" /* Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode, /* for program development only. @@ -441,6 +450,9 @@ typedef struct OPTIONS { ARGV *tas; char *host_lookup; char *addr_pref; +#ifdef USE_TLS + int enable_rpk; +#endif } OPTIONS; /* @@ -696,7 +708,7 @@ static void print_stack(STATE *state, x509_stack_t *sk, int trustout) BIO_printf(state->tls_bio, " cert digest=%s\n", digest); myfree(digest); - digest = tls_pkey_fprint(cert, state->mdalg); + digest = tls_pkey_fprint(X509_get0_pubkey(cert), state->mdalg); BIO_printf(state->tls_bio, " pkey digest=%s\n", digest); myfree(digest); @@ -809,6 +821,7 @@ static int starttls(STATE *state) mdalg = state->mdalg); TLS_PROXY_CLIENT_START_PROPS(&start_props, timeout = smtp_tmout, + enable_rpk = state->options.enable_rpk, tls_level = state->level, nexthop = state->nexthop, host = state->hostname, @@ -826,7 +839,7 @@ static int starttls(STATE *state) state->ddane : state->dane); #define PROXY_OPEN_FLAGS \ - (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT) + (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT) #define var_tlsproxy_service if ((cwd_fd = open(".", O_RDONLY)) < 0) @@ -886,13 +899,19 @@ static int starttls(STATE *state) state->tls_context = tls_proxy_context_receive(state->stream); if (state->tls_context) { if (state->log_mask & - (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) - msg_info("%s: subject_CN=%s, issuer_CN=%s, " - "fingerprint=%s, pkey_fingerprint=%s", - state->namaddrport, state->tls_context->peer_CN, - state->tls_context->issuer_CN, - state->tls_context->peer_cert_fprint, - state->tls_context->peer_pkey_fprint); + (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) { + if (state->tls_context->stoc_rpk) + msg_info("%s: pkey_fingerprint=%s", state->namaddrport, + state->tls_context->peer_pkey_fprint); + else + msg_info("%s: subject_CN=%s, issuer_CN=%s, " + "fingerprint=%s, pkey_fingerprint=%s", + state->namaddrport, + state->tls_context->peer_CN, + state->tls_context->issuer_CN, + state->tls_context->peer_cert_fprint, + state->tls_context->peer_pkey_fprint); + } tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW, state->tls_context); } else { @@ -906,6 +925,7 @@ static int starttls(STATE *state) stream = stream, fd = -1, timeout = smtp_tmout, + enable_rpk = state->options.enable_rpk, tls_level = state->level, nexthop = state->nexthop, host = state->hostname, @@ -938,7 +958,7 @@ static int starttls(STATE *state) if (state->pass == 1) { ehlo(state); - if (!TLS_CERT_IS_PRESENT(state->tls_context)) + if (!TLS_CRED_IS_PRESENT(state->tls_context)) msg_info("Server is anonymous"); else if (state->tlsproxy_mode == 0) { if (state->print_trust) @@ -1232,7 +1252,7 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host, * should not clobber a soft error text and status code. */ #define RETRY_AI_ERROR(e) \ - ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM) + ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM) #ifdef EAI_NODATA #define DSN_NOHOST(e) \ ((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME) @@ -1833,14 +1853,14 @@ static void usage(void) #ifdef USE_TLS fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s \\\n\t%s" " destination [match ...]\n", var_procname, - "[-acCfSvw] [-t conn_tmout] [-T cmd_tmout] [-L logopts]", + "[-acCfRSvwx] [-t conn_tmout] [-T cmd_tmout] [-L logopts]", "[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]", "[-A tafile] [-F CAfile.pem] [-P CApath/] [-s servername]", "[ [-H chainfiles] | [-k certfile [-K keyfile]] ]", "[-m count] [-r delay] [-o name=value]"); #else - fprintf(stderr, "usage: %s [-acStTv] [-h host_lookup] [-o name=value] destination\n", - var_procname); + fprintf(stderr, "usage: %s [-acRStTv] [-h host_lookup] [-o name=value]" + " destination\n", var_procname); #endif exit(1); } @@ -1910,7 +1930,7 @@ static void parse_options(STATE *state, int argc, char *argv[]) #define OPTS "a:ch:o:RSt:T:v" #ifdef USE_TLS -#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wX" +#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wxX" state->mdalg = 0; state->CApath = mystrdup(""); @@ -1921,6 +1941,7 @@ static void parse_options(STATE *state, int argc, char *argv[]) state->sni = mystrdup(""); state->options.tas = argv_alloc(1); state->options.logopts = 0; + state->options.enable_rpk = 0; state->level = TLS_LEV_DANE; state->mxinsec_level = TLS_LEV_DANE; state->tlsproxy_mode = 0; @@ -2054,6 +2075,9 @@ static void parse_options(STATE *state, int argc, char *argv[]) case 'w': state->wrapper_mode = 1; break; + case 'x': + state->options.enable_rpk = 1; + break; case 'X': state->tlsproxy_mode = 1; break; @@ -2119,8 +2143,8 @@ static void parse_match(STATE *state, int argc, char *argv[]) int smtp_mode = 1; /* - * DANE match names are configured late, once the TLSA records are in - * hand. For now, prepare to fall back to "secure". + * DANE match names are configured late, once the TLSA records are in hand. + * For now, prepare to fall back to "secure". */ switch (state->level) { default: @@ -2148,8 +2172,8 @@ static void parse_match(STATE *state, int argc, char *argv[]) case TLS_LEV_FPRINT: state->dane = tls_dane_alloc(); while (*argv) - tls_dane_add_fpt_digests((TLS_DANE *) state->dane, *argv++, "", - smtp_mode); + tls_dane_add_fpt_digests(state->dane, state->options.enable_rpk, + *argv++, "", smtp_mode); break; } #endif diff --git a/src/proxymap/proxymap.c b/src/proxymap/proxymap.c index abdcf3a..c0af411 100644 --- a/src/proxymap/proxymap.c +++ b/src/proxymap/proxymap.c @@ -37,7 +37,7 @@ /* .IP \(bu /* To provide single-updater functionality for lookup tables /* that do not reliably support multiple writers (i.e. all -/* file-based tables). +/* file-based tables that are not based on \fBlmdb\fR). /* .PP /* The \fBproxymap\fR(8) server implements the following requests: /* .IP "\fBopen\fR \fImaptype:mapname flags\fR" @@ -752,8 +752,10 @@ static void post_jail_init(char *service_name, char **unused_argv) if (strcmp(service_name, MAIL_SERVICE_PROXYWRITE) == 0) proxy_writer = 1; else if (strcmp(service_name, MAIL_SERVICE_PROXYMAP) != 0) - msg_fatal("service name must be one of %s or %s", - MAIL_SERVICE_PROXYMAP, MAIL_SERVICE_PROXYMAP); + msg_fatal("invalid service name: \"%s\" - " + "service name must be \"%s\" or \"%s\"", + service_name, MAIL_SERVICE_PROXYWRITE, + MAIL_SERVICE_PROXYMAP); /* * Pre-allocate buffers. @@ -841,6 +843,36 @@ int main(int argc, char **argv) */ MAIL_VERSION_STAMP_ALLOCATE; + /* + * XXX When invoked with the master.cf service name "proxywrite", the + * proxymap daemon will allow update requests. To update a table that is + * not multi-writer safe (for example, some versions of Berkeley DB), the + * "proxywrite" service should run as a single updater (i.e. a process + * limit of 1, which could be enforced below by requesting + * CA_MAIL_SERVER_SOLITARY). + * + * In the default master.cf file, the "proxywrite" service has a process + * limit of 1. Assuming that updates will be rare, this process limit + * will suffice. Latency-sensitive services such as postscreen must not + * use the proxywrite service (in fact, postscreen has a latency check + * built-in). + * + * Optimizing for multi-writer operation would suffer from all kinds of + * complexity that would make it hard to use: + * + * - The master daemon specifies the "proxywrite" service name with the -n + * command-line option. This information is not known here, before the + * multi_server_main() call. The multi_server_main() function could + * reveal process limit information to its call-back functions, and leave + * single-updater enforcement to its call-back functions. + * + * - If we really want multi-writer update support, the "proxywrite" service + * would have to parse the $proxy_write_maps value, and permit + * multi-writer operation only if all tables are multi-writer safe. That + * would require a new dict(3) method, to query each lookup table + * implementation if it is multi-writer safe, without instantiating a + * lookup table client. + */ multi_server_main(argc, argv, proxymap_service, CA_MAIL_SERVER_STR_TABLE(str_table), CA_MAIL_SERVER_POST_INIT(post_jail_init), diff --git a/src/qmgr/qmgr.c b/src/qmgr/qmgr.c index 9d90a6e..25168e4 100644 --- a/src/qmgr/qmgr.c +++ b/src/qmgr/qmgr.c @@ -206,7 +206,7 @@ /* parameter value, where \fItransport\fR is the master.cf name of /* the message delivery transport. /* .IP "\fBdefault_recipient_refill_delay (5s)\fR" -/* The default per-transport maximum delay between recipients refills. +/* The default per-transport maximum delay between refilling recipients. /* .IP "\fBtransport_recipient_refill_delay ($default_recipient_refill_delay)\fR" /* A transport-specific override for the default_recipient_refill_delay /* parameter value, where \fItransport\fR is the master.cf name of diff --git a/src/qmgr/qmgr_deliver.c b/src/qmgr/qmgr_deliver.c index 577bb98..6c880ce 100644 --- a/src/qmgr/qmgr_deliver.c +++ b/src/qmgr/qmgr_deliver.c @@ -160,7 +160,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) */ for (recipient = list.info; recipient < list.info + list.len; recipient++) if (var_smtputf8_enable && (addr = recipient->address)[0] - && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) { + && !allascii(addr) && valid_utf8_stringz(addr)) { smtputf8 |= SMTPUTF8_FLAG_RECIPIENT; if (message->verp_delims) smtputf8 |= SMTPUTF8_FLAG_SENDER; @@ -339,7 +339,7 @@ static void qmgr_deliver_update(int unused_event, void *context) #define SUSPENDED "delivery temporarily suspended: " if (status == DELIVER_STAT_CRASH) - DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error"); + (void) DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error"); if (status == DELIVER_STAT_CRASH || status == DELIVER_STAT_DEFER) { message->flags |= DELIVER_STAT_DEFER; if (VSTRING_LEN(dsb->status)) { diff --git a/src/qmqpd/qmqpd.c b/src/qmqpd/qmqpd.c index d94d33d..138ac64 100644 --- a/src/qmqpd/qmqpd.c +++ b/src/qmqpd/qmqpd.c @@ -57,7 +57,7 @@ /* Preliminary SMTPUTF8 support is introduced with Postfix 3.0. /* .IP "\fBsmtputf8_enable (yes)\fR" /* Enable preliminary SMTPUTF8 support for the protocols described -/* in RFC 6531..6533. +/* in RFC 6531, RFC 6532, and RFC 6533. /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" /* Detect that a message requires SMTPUTF8 support for the specified /* mail origin classes. diff --git a/src/sendmail/sendmail.c b/src/sendmail/sendmail.c index 27b3543..df052c5 100644 --- a/src/sendmail/sendmail.c +++ b/src/sendmail/sendmail.c @@ -412,9 +412,10 @@ /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBremote_header_rewrite_domain (empty)\fR" -/* Don't rewrite message headers from remote clients at all when -/* this parameter is empty; otherwise, rewrite message headers and -/* append the specified domain name to incomplete addresses. +/* Rewrite or add message headers in mail from remote clients if +/* the remote_header_rewrite_domain parameter value is non-empty, +/* updating incomplete addresses with the domain specified in the +/* remote_header_rewrite_domain parameter, and adding missing headers. /* .IP "\fBsyslog_facility (mail)\fR" /* The syslog facility of Postfix logging. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" diff --git a/src/smtp/lmtp_params.c b/src/smtp/lmtp_params.c index bca7cd4..385c81f 100644 --- a/src/smtp/lmtp_params.c +++ b/src/smtp/lmtp_params.c @@ -4,6 +4,7 @@ VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0, VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0, + VAR_LMTP_SASL_PASSWD_RES_DELIM, DEF_LMTP_SASL_PASSWD_RES_DELIM, &var_smtp_sasl_passwd_res_delim, 1, 1, VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0, VAR_LMTP_SASL_PATH, DEF_LMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0, #ifdef USE_TLS @@ -120,6 +121,7 @@ VAR_LMTP_TLS_NOTEOFFER, DEF_LMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer, VAR_LMTP_TLS_BLK_EARLY_MAIL_REPLY, DEF_LMTP_TLS_BLK_EARLY_MAIL_REPLY, &var_smtp_tls_blk_early_mail_reply, VAR_LMTP_TLS_FORCE_TLSA, DEF_LMTP_TLS_FORCE_TLSA, &var_smtp_tls_force_tlsa, + VAR_LMTP_TLS_ENABLE_RPK, DEF_LMTP_TLS_ENABLE_RPK, &var_smtp_tls_enable_rpk, #endif VAR_LMTP_TLS_WRAPPER, DEF_LMTP_TLS_WRAPPER, &var_smtp_tls_wrappermode, VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth, diff --git a/src/smtp/smtp.c b/src/smtp/smtp.c index f7f2fc1..51b2e6d 100644 --- a/src/smtp/smtp.c +++ b/src/smtp/smtp.c @@ -1,17 +1,21 @@ /*++ /* NAME -/* smtp 8 +/* smtp, lmtp 8 /* SUMMARY /* Postfix SMTP+LMTP client /* SYNOPSIS /* \fBsmtp\fR [generic Postfix daemon options] [flags=DORX] +/* +/* \fBlmtp\fR [generic Postfix daemon options] [flags=DORX] /* DESCRIPTION /* The Postfix SMTP+LMTP client implements the SMTP and LMTP mail /* delivery protocols. It processes message delivery requests from /* the queue manager. Each request specifies a queue file, a sender /* address, a domain or host to deliver to, and recipient information. /* This program expects to be run from the \fBmaster\fR(8) process -/* manager. +/* manager. The process name, \fBsmtp\fR or \fBlmtp\fR, controls +/* the protocol, and the names of the configuration parameters +/* that will be used. /* /* The SMTP+LMTP client updates the queue file and marks recipients /* as finished, or it informs the queue manager that delivery should @@ -19,13 +23,9 @@ /* to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as /* appropriate. /* -/* The SMTP+LMTP client looks up a list of mail exchanger addresses for -/* the destination host, sorts the list by preference, and connects -/* to each listed address until it finds a server that responds. -/* -/* When a server is not reachable, or when mail delivery fails due -/* to a recoverable error condition, the SMTP+LMTP client will try to -/* deliver the mail to an alternate host. +/* The server lookup strategy is different for SMTP and LMTP, +/* as described in the sections "SMTP SERVER LOOKUP" and "LMTP +/* SERVER LOOKUP". /* /* After a successful mail transaction, a connection may be saved /* to the \fBscache\fR(8) connection cache server, so that it @@ -35,44 +35,58 @@ /* destinations that have a high volume of mail in the active /* queue. Connection caching can be enabled permanently for /* specific destinations. -/* SMTP DESTINATION SYNTAX +/* SMTP SERVER LOOKUP /* .ad /* .fi -/* The Postfix SMTP+LMTP client supports multiple destinations +/* The Postfix SMTP client supports multiple destinations /* separated by comma or whitespace (Postfix 3.5 and later). +/* Each destination is tried in the specified order. +/* /* SMTP destinations have the following form: /* .IP \fIdomainname\fR -/* .IP \fIdomainname\fR:\fIport\fR +/* .IP \fIdomainname\fR:\fIservice\fR /* Look up the mail exchangers for the specified domain, and -/* connect to the specified port (default: \fBsmtp\fR). +/* connect to the specified service (default: \fBsmtp\fR). +/* Optionally, mail exchangers may be looked up with SRV queries +/* instead of MX; this requires that \fIservice\fR is given +/* in symbolic form. /* .IP [\fIhostname\fR] -/* .IP [\fIhostname\fR]:\fIport\fR -/* Look up the address(es) of the specified host, and connect to -/* the specified port (default: \fBsmtp\fR). +/* .IP [\fIhostname\fR]:\fIservice\fR +/* Look up the address(es) for the specified host, and connect to +/* the specified service (default: \fBsmtp\fR). /* .IP [\fIaddress\fR] -/* .IP [\fIaddress\fR]:\fIport\fR +/* .IP [\fIaddress\fR]:\fIservice\fR /* Connect to the host at the specified address, and connect -/* to the specified port (default: \fBsmtp\fR). An IPv6 address +/* to the specified service (default: \fBsmtp\fR). An IPv6 address /* must be formatted as [\fBipv6\fR:\fIaddress\fR]. -/* LMTP DESTINATION SYNTAX +/* LMTP SERVER LOOKUP /* .ad /* .fi -/* The Postfix SMTP+LMTP client supports multiple destinations +/* The Postfix LMTP client supports multiple destinations /* separated by comma or whitespace (Postfix 3.5 and later). +/* Each destination is tried in the specified order. +/* /* LMTP destinations have the following form: /* .IP \fBunix\fR:\fIpathname\fR /* Connect to the local UNIX-domain server that is bound to the specified /* \fIpathname\fR. If the process runs chrooted, an absolute pathname /* is interpreted relative to the Postfix queue directory. +/* .IP \fBinet\fR:\fIdomainname\fR +/* .IP \fBinet\fR:\fIdomainname\fR:\fIservice\fR +/* Look up the LMTP servers for the specified domain and service +/* (default: \fBlmtp\fR). +/* This form is supported when SRV lookups are enabled, and +/* requires that \fIservice\fR is in symbolic form. /* .IP \fBinet\fR:\fIhostname\fR -/* .IP \fBinet\fR:\fIhostname\fR:\fIport\fR +/* .IP \fBinet\fR:\fIhostname\fR:\fIservice\fR +/* Look up the address(es) for the specified host, and connect to +/* the specified service (default: \fBlmtp\fR). When SRV lookups +/* are enabled, use the form \fB[\fIhostname\fB]\fR to force +/* address lookups. /* .IP \fBinet\fR:[\fIaddress\fR] -/* .IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR -/* Connect to the specified TCP port on the specified local or -/* remote host. If no port is specified, connect to the port defined as -/* \fBlmtp\fR in \fBservices\fR(4). -/* If no such service is found, the \fBlmtp_tcp_port\fR configuration -/* parameter (default value of 24) will be used. +/* .IP \fBinet\fR:[\fIaddress\fR]:\fIservice\fR +/* Connect to the specified local or remote host and service +/* (default: \fBlmtp\fR). /* An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR]. /* SINGLE-RECIPIENT DELIVERY /* .ad @@ -130,6 +144,8 @@ /* This feature is available as of Postfix 3.5. /* .RE /* SECURITY +/* .ad +/* .fi /* The SMTP+LMTP client is moderately security-sensitive. It /* talks to SMTP or LMTP servers and to DNS servers on the /* network. The SMTP+LMTP client can be run chrooted at fixed @@ -175,11 +191,10 @@ /* CONFIGURATION PARAMETERS /* .ad /* .fi -/* Before Postfix version 2.3, the LMTP client is a separate -/* program that implements only a subset of the functionality -/* available with SMTP: there is no support for TLS, and -/* connections are cached in-process, making it ineffective -/* when the client is used for multiple domains. +/* Postfix versions 2.3 and later implement the SMTP and LMTP +/* client with the same program, and choose the protocol and +/* configuration parameters based on the process name, \fBsmtp\fR +/* or \fBlmtp\fR. /* /* Most smtp_\fIxxx\fR configuration parameters have an /* lmtp_\fIxxx\fR "mirror" parameter for the equivalent LMTP @@ -432,6 +447,11 @@ /* .IP "\fBsmtp_send_dummy_mail_auth (no)\fR" /* Whether or not to append the "AUTH=<>" option to the MAIL /* FROM command in SASL-authenticated SMTP sessions. +/* .PP +/* Available in Postfix version 3.9 and later: +/* .IP "\fBsmtp_sasl_password_result_delimiter (:)\fR" +/* The delimiter between username and password in sasl_passwd_maps lookup +/* results. /* STARTTLS SUPPORT CONTROLS /* .ad /* .fi @@ -532,7 +552,7 @@ /* certificate fingerprints. /* .PP /* Available in Postfix version 2.6 and later: -/* .IP "\fBsmtp_tls_protocols (see postconf -d output)\fR" +/* .IP "\fBsmtp_tls_protocols (see 'postconf -d' output)\fR" /* TLS protocols that the Postfix SMTP client will use with /* opportunistic TLS encryption. /* .IP "\fBsmtp_tls_ciphers (medium)\fR" @@ -613,6 +633,11 @@ /* .IP "\fBtls_config_name (empty)\fR" /* The application name passed by Postfix to OpenSSL library /* initialization functions. +/* .PP +/* Available in Postfix version 3.9 and later: +/* .IP "\fBsmtp_tls_enable_rpk (no)\fR" +/* Request that remote SMTP servers send an RFC7250 raw public key +/* instead of an X.509 certificate. /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -799,9 +824,9 @@ /* .IP "\fBdisable_dns_lookups (no)\fR" /* Disable DNS lookups in the Postfix SMTP and LMTP clients. /* .IP "\fBinet_interfaces (all)\fR" -/* The local network interface addresses that this mail system receives -/* mail on. -/* .IP "\fBinet_protocols (see 'postconf -d output')\fR" +/* The local network interface addresses that this mail system +/* receives mail on. +/* .IP "\fBinet_protocols (see 'postconf -d' output)\fR" /* The Internet protocols Postfix will attempt to use when making /* or accepting connections. /* .IP "\fBipc_timeout (3600s)\fR" @@ -1020,6 +1045,7 @@ int var_smtp_never_ehlo; char *var_smtp_sasl_opts; char *var_smtp_sasl_path; char *var_smtp_sasl_passwd; +char *var_smtp_sasl_passwd_res_delim; bool var_smtp_sasl_enable; char *var_smtp_sasl_mechs; char *var_smtp_sasl_type; @@ -1090,6 +1116,7 @@ char *var_smtp_tls_sni; bool var_smtp_tls_blk_early_mail_reply; bool var_smtp_tls_force_tlsa; char *var_smtp_tls_insecure_mx_policy; +bool var_smtp_tls_enable_rpk; #endif @@ -1117,8 +1144,8 @@ bool var_smtp_balance_inet_proto; bool var_smtp_req_deadline; int var_smtp_min_data_rate; char *var_use_srv_lookup; -bool var_ign_srv_lookup_err; -bool var_allow_srv_fallback; +bool var_ign_srv_lookup_err; +bool var_allow_srv_fallback; /* Special handling of 535 AUTH errors. */ char *var_smtp_sasl_auth_cache_name; @@ -1126,7 +1153,7 @@ int var_smtp_sasl_auth_cache_time; bool var_smtp_sasl_auth_soft_bounce; char *var_hfrom_format; -bool var_smtp_bind_addr_enforce; +bool var_smtp_bind_addr_enforce; /* * Global variables. @@ -1458,6 +1485,19 @@ static void pre_init(char *unused_name, char **unused_argv) 0, -1, }; + /* + * The process name, "smtp" or "lmtp", determines the configuration + * parameters to use, protocol, DSN server reply type, SASL service + * information lookup, and more. We peeked at the name in the main() + * function before logging was initialized. Here, we detect and report an + * invalid process name. + */ + if (strcmp(var_procname, MAIL_PROC_NAME_SMTP) != 0 + && strcmp(var_procname, MAIL_PROC_NAME_LMTP) != 0) + msg_fatal("unexpected process name \"%s\" - " + "specify \"%s\" or \"%s\"", var_procname, + MAIL_PROC_NAME_SMTP, MAIL_PROC_NAME_LMTP); + /* * Turn on per-peer debugging. */ @@ -1649,21 +1689,15 @@ int main(int argc, char **argv) MAIL_VERSION_STAMP_ALLOCATE; /* - * XXX At this point, var_procname etc. are not initialized. - * - * The process name, "smtp" or "lmtp", determines the protocol, the DSN - * server reply type, SASL service information lookup, and more. Prepare - * for the possibility there may be another personality. + * XXX The process name, "smtp" or "lmtp", determines what configuration + * parameter settings to use, and more. However, at this point, logging + * and var_procname are not initialized. Here, we peek at the process + * name to determine what configuration parameter settings to use. Later, + * we detect and report an invalid process name. */ sane_procname = sane_basename((VSTRING *) 0, argv[0]); - if (strcmp(sane_procname, "smtp") == 0) + if (strcmp(sane_procname, MAIL_PROC_NAME_SMTP) == 0) smtp_mode = 1; - else if (strcmp(sane_procname, "lmtp") == 0) - smtp_mode = 0; - else - /* TODO: logging is not initialized. */ - msg_fatal("unexpected process name \"%s\" - " - "specify \"smtp\" or \"lmtp\"", var_procname); /* * Initialize with the LMTP or SMTP parameter name space. diff --git a/src/smtp/smtp.h b/src/smtp/smtp.h index f8c8f58..60c68f8 100644 --- a/src/smtp/smtp.h +++ b/src/smtp/smtp.h @@ -107,6 +107,7 @@ typedef struct SMTP_TLS_POLICY { TLS_DANE *dane; /* DANE TLSA digests */ char *sni; /* Optional SNI name when not DANE */ int conn_reuse; /* enable connection reuse */ + int enable_rpk; /* Enable server->client RPK */ } SMTP_TLS_POLICY; /* @@ -142,6 +143,7 @@ extern void smtp_tls_policy_cache_flush(void); _tls_policy_init_tmp->dane = 0; \ _tls_policy_init_tmp->sni = 0; \ _tls_policy_init_tmp->conn_reuse = 0; \ + _tls_policy_init_tmp->enable_rpk = 0; \ } while (0) #endif diff --git a/src/smtp/smtp_addr.c b/src/smtp/smtp_addr.c index f30ce73..8c384fc 100644 --- a/src/smtp/smtp_addr.c +++ b/src/smtp/smtp_addr.c @@ -262,7 +262,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt, msg_fatal("host %s: conversion error for address family " "%d: %m", host, res0->ai_addr->sa_family); addr_list = dns_rr_append(addr_list, addr); - if (DNS_RR_IS_TRUNCATED(addr_list)) + if (DNS_RR_IS_TRUNCATED(addr_list)) break; if (msg_verbose) { MAI_HOSTADDR_STR hostaddr_str; diff --git a/src/smtp/smtp_params.c b/src/smtp/smtp_params.c index 22f4709..cebff93 100644 --- a/src/smtp/smtp_params.c +++ b/src/smtp/smtp_params.c @@ -4,6 +4,7 @@ VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0, VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0, + VAR_SMTP_SASL_PASSWD_RES_DELIM, DEF_SMTP_SASL_PASSWD_RES_DELIM, &var_smtp_sasl_passwd_res_delim, 1, 1, VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0, VAR_SMTP_SASL_PATH, DEF_SMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0, #ifdef USE_TLS @@ -124,6 +125,7 @@ VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer, VAR_SMTP_TLS_BLK_EARLY_MAIL_REPLY, DEF_SMTP_TLS_BLK_EARLY_MAIL_REPLY, &var_smtp_tls_blk_early_mail_reply, VAR_SMTP_TLS_FORCE_TLSA, DEF_SMTP_TLS_FORCE_TLSA, &var_smtp_tls_force_tlsa, + VAR_SMTP_TLS_ENABLE_RPK, DEF_SMTP_TLS_ENABLE_RPK, &var_smtp_tls_enable_rpk, #endif VAR_SMTP_TLS_WRAPPER, DEF_SMTP_TLS_WRAPPER, &var_smtp_tls_wrappermode, VAR_SMTP_SENDER_AUTH, DEF_SMTP_SENDER_AUTH, &var_smtp_sender_auth, diff --git a/src/smtp/smtp_proto.c b/src/smtp/smtp_proto.c index 097d518..e022bc2 100644 --- a/src/smtp/smtp_proto.c +++ b/src/smtp/smtp_proto.c @@ -929,6 +929,7 @@ static int smtp_start_tls(SMTP_STATE *state) TLS_PROXY_CLIENT_START_PROPS(&start_props, timeout = var_smtp_starttls_tmout, tls_level = state->tls->level, + enable_rpk = state->tls->enable_rpk, nexthop = session->tls_nexthop, host = STR(iter->host), namaddr = session->namaddrport, @@ -1051,6 +1052,7 @@ static int smtp_start_tls(SMTP_STATE *state) fd = -1, timeout = var_smtp_starttls_tmout, tls_level = state->tls->level, + enable_rpk = state->tls->enable_rpk, nexthop = session->tls_nexthop, host = STR(iter->host), namaddr = session->namaddrport, diff --git a/src/smtp/smtp_sasl_glue.c b/src/smtp/smtp_sasl_glue.c index ef8e8c4..cce5ef7 100644 --- a/src/smtp/smtp_sasl_glue.c +++ b/src/smtp/smtp_sasl_glue.c @@ -200,7 +200,9 @@ int smtp_sasl_passwd_lookup(SMTP_SESSION *session) if (session->sasl_username) myfree(session->sasl_username); session->sasl_username = mystrdup(value); - passwd = split_at(session->sasl_username, ':'); + /* Historically, the delimiter may appear in the password. */ + passwd = split_at(session->sasl_username, + *var_smtp_sasl_passwd_res_delim); if (session->sasl_passwd) myfree(session->sasl_passwd); session->sasl_passwd = mystrdup(passwd ? passwd : ""); diff --git a/src/smtp/smtp_tls_policy.c b/src/smtp/smtp_tls_policy.c index 92a231d..f407d65 100644 --- a/src/smtp/smtp_tls_policy.c +++ b/src/smtp/smtp_tls_policy.c @@ -334,9 +334,10 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, INVALID_RETURN(tls->why, site_level); break; case TLS_LEV_FPRINT: - if (!tls->dane) - tls->dane = tls_dane_alloc(); - tls_dane_add_fpt_digests(tls->dane, val, "|", smtp_mode); + if (tls->matchargv == 0) + tls->matchargv = argv_split(val, "|"); + else + argv_split_append(tls->matchargv, val, "|"); break; case TLS_LEV_VERIFY: case TLS_LEV_SECURE: @@ -390,6 +391,19 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, } continue; } + if (!strcasecmp(name, "enable_rpk")) { + /* Ultimately ignored at some security levels */ + if (strcasecmp(val, "yes") == 0) { + tls->enable_rpk = 1; + } else if (strcasecmp(val, "no") == 0) { + tls->enable_rpk = 0; + } else { + msg_warn("%s: attribute \"%s\" has bad value: \"%s\"", + WHERE, name, val); + INVALID_RETURN(tls->why, site_level); + } + continue; + } msg_warn("%s: invalid attribute name: \"%s\"", WHERE, name); INVALID_RETURN(tls->why, site_level); } @@ -518,6 +532,7 @@ static void *policy_create(const char *unused_key, void *context) smtp_tls_policy_init(tls, dsb_create()); tls->conn_reuse = var_smtp_tls_conn_reuse; + tls->enable_rpk = var_smtp_tls_enable_rpk; /* * Compute the per-site TLS enforcement level. For compatibility with the @@ -602,6 +617,13 @@ static void *policy_create(const char *unused_key, void *context) */ set_cipher_grade(tls); +/* + * Even when soliciting raw public keys, synthesize TLSA RRs that also match + * certificates. Though this is fragile, it maintains compatibility with + * servers that never return RPKs. + */ +#define DONT_SUPPRESS_CERT_MATCH 0 + /* * Use main.cf cert_match setting if not set in per-destination table. */ @@ -617,16 +639,26 @@ static void *policy_create(const char *unused_key, void *context) case TLS_LEV_FPRINT: if (tls->dane == 0) tls->dane = tls_dane_alloc(); - if (tls->dane->tlsa == 0) { - tls_dane_add_fpt_digests(tls->dane, var_smtp_tls_fpt_cmatch, - CHARS_COMMA_SP, smtp_mode); - if (tls->dane->tlsa == 0) { - msg_warn("nexthop domain %s: configured at fingerprint " - "security level, but with no fingerprints to match.", - dest); - MARK_INVALID(tls->why, &tls->level); - return ((void *) tls); + /* Process the specified fingerprint match patterns */ + if (tls->matchargv) { + int i; + + for (i = 0; i < tls->matchargv->argc; ++i) { + tls_dane_add_fpt_digests(tls->dane, DONT_SUPPRESS_CERT_MATCH, + tls->matchargv->argv[i], "", + smtp_mode); } + } else { + tls_dane_add_fpt_digests(tls->dane, DONT_SUPPRESS_CERT_MATCH, + var_smtp_tls_fpt_cmatch, CHARS_COMMA_SP, + smtp_mode); + } + if (tls->dane->tlsa == 0) { + msg_warn("nexthop domain %s: configured at fingerprint " + "security level, but with no fingerprints to match.", + dest); + MARK_INVALID(tls->why, &tls->level); + return ((void *) tls); } break; case TLS_LEV_VERIFY: diff --git a/src/smtpd/Makefile.in b/src/smtpd/Makefile.in index 7fdfe12..c8837fe 100644 --- a/src/smtpd/Makefile.in +++ b/src/smtpd/Makefile.in @@ -75,7 +75,8 @@ broken-tests: smtpd_check_test smtpd_check_test2 tests: smtpd_acl_test smtpd_addr_valid_test smtpd_exp_test \ smtpd_token_test smtpd_check_test4 smtpd_check_dsn_test \ smtpd_check_backup_test smtpd_dnswl_test smtpd_error_test \ - smtpd_server_test smtpd_nullmx_test smtpd_dns_filter_test + smtpd_server_test smtpd_nullmx_test smtpd_dns_filter_test \ + smtpd_deprecated_test root_tests: @@ -114,7 +115,8 @@ smtpd_addr_valid_test: smtpd_check smtpd_addr_valid.in smtpd_addr_valid.ref # This requires that the DNS server can query porcupine.org. -ADDRINFO_FIX = sed 's/No address associated with hostname/hostname nor servname provided, or not known/' +ADDRINFO_FIX = sed -e 's/No address associated with hostname/hostname nor servname provided, or not known/' \ + -e 's/Name or service not known/hostname nor servname provided, or not known/' smtpd_exp_test: smtpd_check smtpd_exp.in smtpd_exp.ref $(SHLIB_ENV) $(VALGRIND) ../postmap/postmap hash:smtpd_check_access @@ -170,6 +172,11 @@ smtpd_error_test: smtpd_check smtpd_error.in smtpd_error.ref diff smtpd_error.ref smtpd_check.tmp rm -f smtpd_check.tmp +smtpd_deprecated_test: smtpd_check smtpd_deprecated.in smtpd_deprecated.ref + $(SHLIB_ENV) $(VALGRIND) ./smtpd_check smtpd_check.tmp 2>&1 + diff smtpd_deprecated.ref smtpd_check.tmp + rm -f smtpd_check.tmp + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ diff --git a/src/smtpd/smtpd.c b/src/smtpd/smtpd.c index 6a2cf01..bce0d43 100644 --- a/src/smtpd/smtpd.c +++ b/src/smtpd/smtpd.c @@ -468,7 +468,7 @@ /* \fBcheck_ccert_access\fR and \fBpermit_tls_clientcerts\fR. /* .PP /* Available in Postfix version 2.6 and later: -/* .IP "\fBsmtpd_tls_protocols (see postconf -d output)\fR" +/* .IP "\fBsmtpd_tls_protocols (see 'postconf -d' output)\fR" /* TLS protocols accepted by the Postfix SMTP server with opportunistic /* TLS encryption. /* .IP "\fBsmtpd_tls_ciphers (medium)\fR" @@ -537,6 +537,12 @@ /* .IP "\fBtls_config_name (empty)\fR" /* The application name passed by Postfix to OpenSSL library /* initialization functions. +/* .PP +/* Available in Postfix version 3.9 and later: +/* .IP "\fBsmtpd_tls_enable_rpk (no)\fR" +/* Request that remote SMTP clients send an RFC7250 raw public key +/* instead of an X.509 certificate, when asking for or requiring client +/* authentication. /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -662,12 +668,12 @@ /* The list of domains that are delivered via the $local_transport /* mail delivery transport. /* .IP "\fBinet_interfaces (all)\fR" -/* The local network interface addresses that this mail system receives -/* mail on. +/* The local network interface addresses that this mail system +/* receives mail on. /* .IP "\fBproxy_interfaces (empty)\fR" /* The remote network interface addresses that this mail system receives mail /* on by way of a proxy or network address translation unit. -/* .IP "\fBinet_protocols (see 'postconf -d output')\fR" +/* .IP "\fBinet_protocols (see 'postconf -d' output)\fR" /* The Internet protocols Postfix will attempt to use when making /* or accepting connections. /* .IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR" @@ -698,8 +704,9 @@ /* alias domains, that is, domains for which all addresses are aliased /* to addresses in other local or remote domains. /* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" -/* Optional lookup tables that alias specific mail addresses or domains -/* to other local or remote addresses. +/* Optional lookup tables with aliases that apply to all recipients: +/* \fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply +/* only to \fBlocal\fR(8) recipients. /* .IP "\fBunknown_virtual_alias_reject_code (550)\fR" /* The Postfix SMTP server reply code when a recipient address matches /* $virtual_alias_domains, and $virtual_alias_maps specifies a list @@ -817,7 +824,7 @@ /* command pipelining constraints. /* .PP /* Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: -/* .IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR" +/* .IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: normalize)\fR" /* Reject or restrict input lines from an SMTP client that end in /* instead of the standard . /* .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR" @@ -1492,6 +1499,7 @@ char *var_smtpd_tls_eecdh; char *var_smtpd_tls_eccert_file; char *var_smtpd_tls_eckey_file; char *var_smtpd_tls_chain_files; +int var_smtpd_tls_enable_rpk; #endif @@ -1664,13 +1672,16 @@ int smtpd_hfrom_format; */ #define BARE_LF_FLAG_WANT_STD_EOD (1<<0) /* Require CRLF.CRLF */ #define BARE_LF_FLAG_REPLY_REJECT (1<<1) /* Reject bare newline */ +#define BARE_LF_FLAG_NOTE_LOG (1<<2) /* Note bare newline */ #define IS_BARE_LF_WANT_STD_EOD(m) ((m) & BARE_LF_FLAG_WANT_STD_EOD) #define IS_BARE_LF_REPLY_REJECT(m) ((m) & BARE_LF_FLAG_REPLY_REJECT) +#define IS_BARE_LF_NOTE_LOG(m) ((m) & BARE_LF_FLAG_NOTE_LOG) static const NAME_CODE bare_lf_mask_table[] = { "normalize", BARE_LF_FLAG_WANT_STD_EOD, /* Default */ "yes", BARE_LF_FLAG_WANT_STD_EOD, /* Migration aid */ + "note", BARE_LF_FLAG_WANT_STD_EOD | BARE_LF_FLAG_NOTE_LOG, "reject", BARE_LF_FLAG_WANT_STD_EOD | BARE_LF_FLAG_REPLY_REJECT, "no", 0, 0, -1, /* error */ @@ -3504,11 +3515,15 @@ static void common_pre_message_handling(SMTPD_STATE *state, } if (state->tls_context->srvr_sig_curve && *state->tls_context->srvr_sig_curve) - vstring_sprintf_append(state->buffer, " (%s)", - state->tls_context->srvr_sig_curve); + vstring_sprintf_append(state->buffer, " (%s%s)", + state->tls_context->srvr_sig_curve, + state->tls_context->stoc_rpk ? + " raw public key" : ""); else if (state->tls_context->srvr_sig_bits > 0) - vstring_sprintf_append(state->buffer, " (%d bits)", - state->tls_context->srvr_sig_bits); + vstring_sprintf_append(state->buffer, " (%d bit%s)", + state->tls_context->srvr_sig_bits, + state->tls_context->stoc_rpk ? + " raw public key" : "s"); if (state->tls_context->srvr_sig_dgst && *state->tls_context->srvr_sig_dgst) vstring_sprintf_append(state->buffer, " server-digest %s", @@ -3522,11 +3537,15 @@ static void common_pre_message_handling(SMTPD_STATE *state, state->tls_context->clnt_sig_name); if (state->tls_context->clnt_sig_curve && *state->tls_context->clnt_sig_curve) - vstring_sprintf_append(state->buffer, " (%s)", - state->tls_context->clnt_sig_curve); + vstring_sprintf_append(state->buffer, " (%s%s)", + state->tls_context->clnt_sig_curve, + state->tls_context->ctos_rpk ? + " raw public key" : ""); else if (state->tls_context->clnt_sig_bits > 0) - vstring_sprintf_append(state->buffer, " (%d bits)", - state->tls_context->clnt_sig_bits); + vstring_sprintf_append(state->buffer, " (%d bit%s)", + state->tls_context->clnt_sig_bits, + state->tls_context->ctos_rpk ? + " raw public key" : "s"); if (state->tls_context->clnt_sig_dgst && *state->tls_context->clnt_sig_dgst) vstring_sprintf_append(state->buffer, " client-digest %s", @@ -3546,6 +3565,11 @@ static void common_pre_message_handling(SMTPD_STATE *state, "verified OK" : "not verified"); vstring_free(issuer_CN); vstring_free(peer_CN); + } else if (TLS_RPK_IS_PRESENT(state->tls_context)) { + out_fprintf(out_stream, REC_TYPE_NORM, + "\t(Client RPK %s digest %s)", + var_smtpd_tls_fpt_dgst, + state->tls_context->peer_pkey_fprint); } else if (var_smtpd_tls_ask_ccert) out_fprintf(out_stream, REC_TYPE_NORM, "\t(Client did not present a certificate)"); @@ -3648,6 +3672,8 @@ static void receive_data_message(SMTPD_STATE *state, curr_rec_type = REC_TYPE_CONT; if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) state->err |= CLEANUP_STAT_BARE_LF; + else if (IS_BARE_LF_NOTE_LOG(smtp_got_bare_lf)) + state->notes |= SMTPD_NOTE_BARE_LF; start = vstring_str(state->buffer); len = VSTRING_LEN(state->buffer); if (first) { @@ -4168,6 +4194,8 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) } if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) state->err |= CLEANUP_STAT_BARE_LF; + else if (IS_BARE_LF_NOTE_LOG(smtp_got_bare_lf)) + state->notes |= SMTPD_NOTE_BARE_LF; start = vstring_str(state->bdat_get_buffer); len = VSTRING_LEN(state->bdat_get_buffer); if (state->err == CLEANUP_STAT_OK) { @@ -5231,6 +5259,7 @@ static void smtpd_start_tls(SMTPD_STATE *state) stream = state->client, fd = -1, timeout = var_smtpd_starttls_tmout, + enable_rpk = var_smtpd_tls_enable_rpk, requirecert = requirecert, serverid = state->service, namaddr = state->namaddr, @@ -5469,8 +5498,6 @@ static void tls_reset(SMTPD_STATE *state) #endif -#if !defined(USE_TLS) || !defined(USE_SASL_AUTH) - /* unimpl_cmd - dummy for functionality that is not compiled in */ static int unimpl_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) @@ -5487,8 +5514,6 @@ static int unimpl_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) return (-1); } -#endif - /* * The table of all SMTP commands that we know. Set the junk limit flag on * any command that can be repeated an arbitrary number of times without @@ -5513,6 +5538,8 @@ typedef struct SMTPD_CMD { #define SMTPD_CMD_FLAG_PRE_TLS (1<<1) /* allow before STARTTLS */ #define SMTPD_CMD_FLAG_LAST (1<<2) /* last in PIPELINING command group */ +static int help_cmd(SMTPD_STATE *, int, SMTPD_TOKEN *); + static SMTPD_CMD smtpd_cmd_table[] = { {SMTPD_CMD_HELO, helo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS | SMTPD_CMD_FLAG_LAST,}, {SMTPD_CMD_EHLO, ehlo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS | SMTPD_CMD_FLAG_LAST,}, @@ -5537,12 +5564,44 @@ static SMTPD_CMD smtpd_cmd_table[] = { {SMTPD_CMD_VRFY, vrfy_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_LAST,}, {SMTPD_CMD_ETRN, etrn_cmd, SMTPD_CMD_FLAG_LIMIT,}, {SMTPD_CMD_QUIT, quit_cmd, SMTPD_CMD_FLAG_PRE_TLS,}, + {SMTPD_CMD_HELP, help_cmd, SMTPD_CMD_FLAG_PRE_TLS,}, {0,}, }; static STRING_LIST *smtpd_noop_cmds; static STRING_LIST *smtpd_forbid_cmds; +/* help_cmd - process HELP command */ + +static int help_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_argv) +{ + ARGV *argv = argv_alloc(sizeof(smtpd_cmd_table) + / sizeof(*smtpd_cmd_table)); + VSTRING *buf = vstring_alloc(100); + SMTPD_CMD *cmdp; + + /* + * Return a list of implemented commands. + * + * The HELP command does not suppress commands that can be dynamically + * disabled in the EHLO response or through access control. That would + * require refactoring the EHLO feature-suppression and per-feature + * access control, so that they can be reused (not duplicated) here. + * + * The HELP command does not provide information that makes Postfix easier + * to fingerprint, such as software name, version, or build information. + */ + for (cmdp = smtpd_cmd_table; cmdp->name != 0; cmdp++) + if (cmdp->action != unimpl_cmd) + argv_add(argv, cmdp->name, ARGV_END); + argv_sort(argv); + smtpd_chat_reply(state, "214 2.0.0 Commands: %s", + argv_join(buf, argv, ' ')); + vstring_free(buf); + argv_free(argv); + return (0); +} + /* smtpd_flag_ill_pipelining - flag pipelining protocol violation */ static int smtpd_flag_ill_pipelining(SMTPD_STATE *state) @@ -5869,9 +5928,11 @@ static void smtpd_proto(SMTPD_STATE *state) var_smtpd_forbid_bare_lf_code, var_myhostname); break; } + if (IS_BARE_LF_NOTE_LOG(smtp_got_bare_lf)) + state->notes |= SMTPD_NOTE_BARE_LF; /* Safety: protect internal interfaces against malformed UTF-8. */ - if (var_smtputf8_enable && valid_utf8_string(STR(state->buffer), - LEN(state->buffer)) == 0) { + if (var_smtputf8_enable + && valid_utf8_stringz(STR(state->buffer)) == 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "500 5.5.2 Error: bad UTF-8 syntax"); state->error_count++; @@ -6055,11 +6116,12 @@ static void smtpd_proto(SMTPD_STATE *state) /* smtpd_format_cmd_stats - format per-command statistics */ -static char *smtpd_format_cmd_stats(VSTRING *buf) +static char *smtpd_format_cmd_stats(SMTPD_STATE *state) { SMTPD_CMD *cmdp; int all_success = 0; int all_total = 0; + VSTRING *buf = state->buffer; /* * Log the statistics. Note that this loop produces no output when no @@ -6103,6 +6165,13 @@ static char *smtpd_format_cmd_stats(VSTRING *buf) vstring_sprintf_append(buf, " commands=%d", all_success); if (all_success != all_total || all_total == 0) vstring_sprintf_append(buf, "/%d", all_total); + + /* + * Log aggregated warnings. + */ + if (state->notes & SMTPD_NOTE_BARE_LF) + vstring_sprintf_append(buf, " notes=bare_lf"); + return (lowercase(STR(buf))); } @@ -6244,7 +6313,7 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv) * connection time. */ msg_info("disconnect from %s%s", state.namaddr, - smtpd_format_cmd_stats(state.buffer)); + smtpd_format_cmd_stats(&state)); teardown_milters(&state); /* duplicates xclient_cmd */ smtpd_state_reset(&state); debug_peer_restore(); @@ -6403,7 +6472,6 @@ static void pre_jail_init(char *unused_name, char **unused_argv) no_server_cert_ok = 0; cert_file = var_smtpd_tls_cert_file; } - have_server_cert = *cert_file != 0; have_server_cert |= *var_smtpd_tls_eccert_file != 0; have_server_cert |= *var_smtpd_tls_dcert_file != 0; @@ -6653,6 +6721,7 @@ int main(int argc, char **argv) #ifdef USE_TLS VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert, VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert, + VAR_SMTPD_TLS_ENABLE_RPK, DEF_SMTPD_TLS_ENABLE_RPK, &var_smtpd_tls_enable_rpk, VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header, VAR_SMTPD_TLS_SET_SESSID, DEF_SMTPD_TLS_SET_SESSID, &var_smtpd_tls_set_sessid, #endif diff --git a/src/smtpd/smtpd.h b/src/smtpd/smtpd.h index 56ebc07..c049194 100644 --- a/src/smtpd/smtpd.h +++ b/src/smtpd/smtpd.h @@ -114,6 +114,7 @@ typedef struct { int junk_cmds; /* counter */ int rcpt_overshoot; /* counter */ char *rewrite_context; /* address rewriting context */ + int notes; /* notes aggregator */ /* * SASL specific. @@ -209,6 +210,8 @@ typedef struct { #define SMTPD_FLAG_SMTPUTF8 (1<<3) /* RFC 6531/2 transaction */ #define SMTPD_FLAG_NEED_MILTER_ABORT (1<<4) /* undo milter_mail_event() */ +#define SMTPD_NOTE_BARE_LF (1<<0) /* saw at least one bare LF */ + /* Security: don't reset SMTPD_FLAG_AUTH_USED. */ #define SMTPD_MASK_MAIL_KEEP \ ~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */ @@ -260,6 +263,7 @@ extern void smtpd_state_reset(SMTPD_STATE *); #define SMTPD_CMD_XCLIENT "XCLIENT" #define SMTPD_CMD_XFORWARD "XFORWARD" #define SMTPD_CMD_UNKNOWN "UNKNOWN" +#define SMTPD_CMD_HELP "HELP" /* * Representation of unknown and non-existent client information. Throughout diff --git a/src/smtpd/smtpd_check.c b/src/smtpd/smtpd_check.c index 093aa06..6aeda74 100644 --- a/src/smtpd/smtpd_check.c +++ b/src/smtpd/smtpd_check.c @@ -1598,6 +1598,7 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient); static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) { #ifdef USE_TLS + const char *myname = "permit_tls_clientcerts"; const char *found = 0; if (!state->tls_context) @@ -1612,9 +1613,9 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) /* * When directly checking the fingerprint, it is OK if the issuing CA is - * not trusted. + * not trusted. Raw public keys are also acceptable. */ - if (TLS_CERT_IS_PRESENT(state->tls_context)) { + if (TLS_CRED_IS_PRESENT(state->tls_context)) { int i; char *prints[2]; @@ -1623,12 +1624,24 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs) VAR_SMTPD_TLS_FPT_DGST "=md5 to compute certificate " "fingerprints"); - prints[0] = state->tls_context->peer_cert_fprint; - prints[1] = state->tls_context->peer_pkey_fprint; + prints[0] = state->tls_context->peer_pkey_fprint; + prints[1] = state->tls_context->peer_cert_fprint; /* After lookup error, leave relay_ccerts->error at non-zero value. */ for (i = 0; i < 2; ++i) { + /* With RFC7250 RPK, no certificate may be available */ + if (!*prints[i]) + continue; found = maps_find(relay_ccerts, prints[i], DICT_FLAG_NONE); + if (var_smtpd_tls_enable_rpk && i > 0 && found) { + msg_warn("%s: %s: %s: Fragile access policy: %s=yes, but" + " public key fingerprint \"%s\" not matched, while" + " certificate fingerprint \"%s\" matched", + myname, state->namaddr, relay_ccerts->title, + VAR_SMTPD_TLS_ENABLE_RPK, + state->tls_context->peer_cert_fprint, + state->tls_context->peer_pkey_fprint); + } if (found != 0) { if (msg_verbose) msg_info("Relaying allowed for certified client: %s", found); @@ -1659,44 +1672,16 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient, { const char *myname = "check_relay_domains"; -#if 1 - static int once; - - if (once == 0) { - once = 1; - msg_warn("support for restriction \"%s\" will be removed from %s; " - "use \"%s\" instead", - CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST); - } -#endif - - if (msg_verbose) - msg_info("%s: %s", myname, recipient); - /* - * Permit if the client matches the relay_domains list. + * Restriction check_relay_domains is deprecated as of Postfix 2.2. */ - if (domain_list_match(relay_domains, state->name)) { - if (warn_compat_break_relay_domains) - msg_info("using backwards-compatible default setting " - VAR_RELAY_DOMAINS "=$mydestination to permit " - "request from client \"%s\"", state->name); - return (SMTPD_CHECK_OK); - } - - /* - * Permit authorized destinations. - */ - if (permit_auth_destination(state, recipient) == SMTPD_CHECK_OK) - return (SMTPD_CHECK_OK); + if (msg_verbose) + msg_info("%s: %s", myname, recipient); - /* - * Deny relaying between sites that both are not in relay_domains. - */ - return (smtpd_check_reject(state, MAIL_ERROR_POLICY, - var_relay_code, "5.7.1", - "<%s>: %s rejected: Relay access denied", - reply_name, reply_class)); + msg_warn("support for restriction \"%s\" has been removed in %s 3.9; " + "instead, specify \"%s\"", + CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST); + reject_server_error(state); } /* permit_auth_destination - OK for message relaying */ @@ -2002,10 +1987,21 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient, DNS_RR *middle; DNS_RR *rest; int dns_status; + static int once; if (msg_verbose) msg_info("%s: %s", myname, recipient); + /* + * Restriction permit_mx_backup is deprecated as of Postfix 3.9. + */ + if (once == 0) { + once = 1; + msg_warn("support for restriction \"%s\" will be removed from %s; " + "instead, specify \"%s\"", + PERMIT_MX_BACKUP, var_mail_name, VAR_RELAY_DOMAINS); + } + /* * Resolve the address. */ @@ -3185,6 +3181,9 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, #ifdef USE_TLS const char *myname = "check_ccert_access"; + int cert_result = SMTPD_CHECK_DUNNO; + int pkey_result = SMTPD_CHECK_DUNNO; + int *respt; int found; const MAP_SEARCH *acl; const char default_search[] = { @@ -3211,9 +3210,9 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, /* * When directly checking the fingerprint, it is OK if the issuing CA is - * not trusted. + * not trusted. Raw public keys are also acceptable. */ - if (TLS_CERT_IS_PRESENT(state->tls_context)) { + if (TLS_CRED_IS_PRESENT(state->tls_context)) { const char *action; const char *match_this; const char *known_action; @@ -3222,17 +3221,19 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, switch (*action) { case SMTPD_ACL_SEARCH_CODE_CERT_FPRINT: match_this = state->tls_context->peer_cert_fprint; - if (warn_compat_break_smtpd_tls_fpt_dgst) + if (*match_this && warn_compat_break_smtpd_tls_fpt_dgst) msg_info("using backwards-compatible default setting " VAR_SMTPD_TLS_FPT_DGST "=md5 to compute " "certificate fingerprints"); + respt = &cert_result; break; case SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT: match_this = state->tls_context->peer_pkey_fprint; - if (warn_compat_break_smtpd_tls_fpt_dgst) + if (*match_this && warn_compat_break_smtpd_tls_fpt_dgst) msg_info("using backwards-compatible default setting " VAR_SMTPD_TLS_FPT_DGST "=md5 to compute " - "certificate fingerprints"); + "public key fingerprints"); + respt = &pkey_result; break; default: known_action = str_name_code(search_actions, *action); @@ -3245,6 +3246,9 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, 451, "4.3.5", "Server configuration error")); } + /* With RFC7250 RPK, no certificate may be available */ + if (!*match_this) + continue; if (msg_verbose) msg_info("%s: look up %s %s", myname, str_name_code(search_actions, *action), @@ -3257,11 +3261,16 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, * "reject" event. XXX Should log the thing that is rejected * (fingerprint etc.) or would that give away too much? */ - result = check_access(state, acl->map_type_name, match_this, + *respt = check_access(state, acl->map_type_name, match_this, DICT_FLAG_NONE, &found, state->tls_context->peer_CN, SMTPD_NAME_CCERT, def_acl); - if (result != SMTPD_CHECK_DUNNO) + if (*respt == SMTPD_CHECK_DUNNO) + continue; + if (result == SMTPD_CHECK_DUNNO) + result = *respt; + if (!var_smtpd_tls_enable_rpk + || *action == SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT) break; } } else if (!var_smtpd_tls_ask_ccert) { @@ -3271,6 +3280,17 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec, if (msg_verbose) msg_info("%s: no client certificate", myname); } + if (var_smtpd_tls_enable_rpk + && cert_result != SMTPD_CHECK_DUNNO + && cert_result != pkey_result) { + msg_warn("%s: %s: %s: Fragile access policy: %s=yes, but" + " the action for certificate fingerprint \"%s\" !=" + " the action for public key fingerprint \"%s\"", + myname, state->namaddr, acl->map_type_name, + VAR_SMTPD_TLS_ENABLE_RPK, + state->tls_context->peer_cert_fprint, + state->tls_context->peer_pkey_fprint); + } #endif return (result); } @@ -3877,34 +3897,18 @@ static int permit_dnswl_domain(SMTPD_STATE *state, const char *dnswl_domain, static int reject_maps_rbl(SMTPD_STATE *state) { const char *myname = "reject_maps_rbl"; - char *saved_domains = mystrdup(var_maps_rbl_domains); - char *bp = saved_domains; - char *rbl_domain; - int result = SMTPD_CHECK_DUNNO; - static int warned; if (msg_verbose) msg_info("%s: %s", myname, state->addr); - if (warned == 0) { - warned++; - msg_warn("support for restriction \"%s\" will be removed from %s; " - "use \"%s domain-name\" instead", - REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT); - } - while ((rbl_domain = mystrtok(&bp, CHARS_COMMA_SP)) != 0) { - result = reject_rbl_addr(state, rbl_domain, state->addr, - SMTPD_NAME_CLIENT); - if (result != SMTPD_CHECK_DUNNO) - break; - } - /* - * Clean up. + * Restriction reject_maps_rbl is deprecated as of Postfix 2.1. */ - myfree(saved_domains); + msg_warn("support for restriction \"%s\" has been removed in %s 3.9; " + "instead, specify \"%s domain-name\"", + REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT); - return (result); + reject_server_error(state); } #ifdef USE_SASL_AUTH @@ -3980,7 +3984,7 @@ static int valid_utf8_action(const char *server, const char *action) { int retval; - if ((retval = valid_utf8_string(action, strlen(action))) == 0) + if ((retval = valid_utf8_stringz(action)) == 0) msg_warn("malformed UTF-8 in policy server %s response: \"%s\"", server, action); return (retval); @@ -4035,6 +4039,8 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, ENCODE_CN(subject, subject_buf, state->tls_context->peer_CN); ENCODE_CN(issuer, issuer_buf, state->tls_context->issuer_CN); +#define NONEMPTY(x) ((x) != 0 && (*x) != 0) + /* * XXX: Too noisy to warn for each policy lookup, especially because we * don't even know whether the policy server will use the fingerprint. So @@ -4044,12 +4050,12 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, if (!warned && warn_compat_break_smtpd_tls_fpt_dgst && state->tls_context - && state->tls_context->peer_cert_fprint - && *state->tls_context->peer_cert_fprint) { + && (NONEMPTY(state->tls_context->peer_cert_fprint) + || NONEMPTY(state->tls_context->peer_pkey_fprint))) { warned = 1; msg_info("using backwards-compatible default setting " VAR_SMTPD_TLS_FPT_DGST "=md5 to compute certificate " - "fingerprints"); + "and public key fingerprints"); } #endif @@ -4480,15 +4486,12 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, state->helo_name, SMTPD_NAME_HELO); } } else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) { - msg_warn("restriction %s is deprecated. Use %s or %s instead", - PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS, PERMIT_SASL_AUTH); - if (state->helo_name) { - if (state->helo_name[strspn(state->helo_name, "0123456789.:")] == 0 - && (status = reject_invalid_hostaddr(state, state->helo_name, - state->helo_name, SMTPD_NAME_HELO)) == 0) - status = smtpd_acl_permit(state, name, SMTPD_NAME_HELO, - state->helo_name, NO_PRINT_ARGS); - } + /* permit_naked_ip_addr is deprecated as of Postfix 2.0. */ + msg_warn("support for restriction \"%s\" has been removed in %s" + " 3.9; instead, specify \"%s\" or \"%s\"", + PERMIT_NAKED_IP_ADDR, var_mail_name, + PERMIT_MYNETWORKS, PERMIT_SASL_AUTH); + reject_server_error(state); } else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) { if (state->helo_name) { status = check_server_access(state, *cpp, state->helo_name, @@ -5255,8 +5258,9 @@ static int check_recipient_rcpt_maps(SMTPD_STATE *state, const char *recipient) { /* - * Duplicate suppression. There's an implicit check_recipient_maps - * restriction at the end of all recipient restrictions. + * Duplicate suppression. With "smtpd_reject_unlisted_recipient = yes", + * there's an implicit reject_unlisted_recipient restriction at the end + * of all recipient restrictions. */ if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT) return (0); @@ -5275,8 +5279,9 @@ static int check_sender_rcpt_maps(SMTPD_STATE *state, const char *sender) { /* - * Duplicate suppression. There's an implicit check_sender_maps - * restriction at the end of all sender restrictions. + * Duplicate suppression. With "smtpd_reject_unlisted_sender = yes", + * there's an implicit reject_unlisted_sender restriction at the end of + * all sender restrictions. */ if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT) return (0); @@ -5832,6 +5837,7 @@ char *var_smtpd_dns_re_filter; bool var_smtpd_tls_ask_ccert; int var_smtpd_cipv4_prefix; int var_smtpd_cipv6_prefix; +bool var_smtpd_tls_enable_rpk; #define int_table test_int_table @@ -5869,6 +5875,7 @@ static const INT_TABLE int_table[] = { VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert, VAR_SMTPD_CIPV4_PREFIX, DEF_SMTPD_CIPV4_PREFIX, &var_smtpd_cipv4_prefix, VAR_SMTPD_CIPV6_PREFIX, DEF_SMTPD_CIPV6_PREFIX, &var_smtpd_cipv6_prefix, + VAR_SMTPD_TLS_ENABLE_RPK, DEF_SMTPD_TLS_ENABLE_RPK, &var_smtpd_tls_enable_rpk, 0, }; @@ -6406,7 +6413,7 @@ int main(int argc, char **argv) state.tls_context->peer_cert_fprint = state.tls_context->peer_pkey_fprint = 0; } - state.tls_context->peer_status |= TLS_CERT_FLAG_PRESENT; + state.tls_context->peer_status |= TLS_CRED_FLAG_CERT; UPDATE_STRING(state.tls_context->peer_cert_fprint, args->argv[1]); state.tls_context->peer_pkey_fprint = diff --git a/src/smtpd/smtpd_check_backup.ref b/src/smtpd/smtpd_check_backup.ref index 8f4a0f2..c15be35 100644 --- a/src/smtpd/smtpd_check_backup.ref +++ b/src/smtpd/smtpd_check_backup.ref @@ -17,6 +17,7 @@ OK >>> recipient_restrictions permit_mx_backup,reject OK >>> rcpt wietse@wzv.porcupine.org +./smtpd_check: warning: support for restriction "permit_mx_backup" will be removed from Postfix; instead, use "relay_domains" OK >>> rcpt wietse@backup.porcupine.org OK diff --git a/src/smtpd/smtpd_deprecated.in b/src/smtpd/smtpd_deprecated.in new file mode 100644 index 0000000..345ee71 --- /dev/null +++ b/src/smtpd/smtpd_deprecated.in @@ -0,0 +1,20 @@ +# +# permit_naked_ip_address +# +client foo 127.0.0.2 +recipient_restrictions permit_naked_ip_address +helo 127.0.0.2 +mail sname@sdomain.example +rcpt rname@rdomain.example +# +# check_relay_domains +# +client foo 127.0.0.2 +recipient_restrictions check_relay_domains +relay_domains foo +helo 127.0.0.2 +mail sname@sdomain.example +rcpt rname@rdomain.example +# +# reject_maps_rbl is already covered elsewhere. +# diff --git a/src/smtpd/smtpd_deprecated.ref b/src/smtpd/smtpd_deprecated.ref new file mode 100644 index 0000000..d64f1b3 --- /dev/null +++ b/src/smtpd/smtpd_deprecated.ref @@ -0,0 +1,35 @@ +>>> # +>>> # permit_naked_ip_address +>>> # +>>> client foo 127.0.0.2 +OK +>>> recipient_restrictions permit_naked_ip_address +OK +>>> helo 127.0.0.2 +OK +>>> mail sname@sdomain.example +OK +>>> rcpt rname@rdomain.example +./smtpd_check: warning: restriction permit_naked_ip_address has been removed in Postfix 3.9; use permit_mynetworks or permit_sasl_authenticated instead +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: 451 4.3.5 Server configuration error; from= to= proto=SMTP helo=<127.0.0.2> +451 4.3.5 Server configuration error +>>> # +>>> # check_relay_domains +>>> # +>>> client foo 127.0.0.2 +OK +>>> recipient_restrictions check_relay_domains +OK +>>> relay_domains foo +OK +>>> helo 127.0.0.2 +OK +>>> mail sname@sdomain.example +OK +>>> rcpt rname@rdomain.example +./smtpd_check: warning: support for restriction "check_relay_domains" has been removed in Postfix 3.9; use "reject_unauth_destination" instead +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: 451 4.3.5 Server configuration error; from= to= proto=SMTP helo=<127.0.0.2> +451 4.3.5 Server configuration error +>>> # +>>> # reject_maps_rbl is already covered elsewhere. +>>> # diff --git a/src/smtpd/smtpd_exp.ref b/src/smtpd/smtpd_exp.ref index 22c027e..00848a5 100644 --- a/src/smtpd/smtpd_exp.ref +++ b/src/smtpd/smtpd_exp.ref @@ -25,13 +25,15 @@ OK >>> client spike.porcupine.org 168.100.3.2 OK >>> rcpt rname@rdomain -./smtpd_check: warning: support for restriction "reject_maps_rbl" will be removed from Postfix; use "reject_rbl_client domain-name" instead -OK +./smtpd_check: warning: support for restriction "reject_maps_rbl" has been removed in Postfix 3.9; use "reject_rbl_client domain-name" instead +./smtpd_check: : reject: RCPT from spike.porcupine.org[168.100.3.2]: 451 4.3.5 Server configuration error; from= to= proto=SMTP helo= +451 4.3.5 Server configuration error >>> client foo 127.0.0.2 OK >>> rcpt rname@rdomain -./smtpd_check: : reject: RCPT from foo[127.0.0.2]: 554 5.7.1 Service unavailable; Client host [127.0.0.2] blocked using dnsbltest.porcupine.org; DNS blocklist test; from= to= proto=SMTP helo= -554 5.7.1 Service unavailable; Client host [127.0.0.2] blocked using dnsbltest.porcupine.org; DNS blocklist test +./smtpd_check: warning: support for restriction "reject_maps_rbl" has been removed in Postfix 3.9; use "reject_rbl_client domain-name" instead +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: 451 4.3.5 Server configuration error; from= to= proto=SMTP helo= +451 4.3.5 Server configuration error >>> # >>> recipient_restrictions reject_rbl_client,dnsbltest.porcupine.org OK diff --git a/src/smtpd/smtpd_sasl_glue.c b/src/smtpd/smtpd_sasl_glue.c index d9db7b0..1163366 100644 --- a/src/smtpd/smtpd_sasl_glue.c +++ b/src/smtpd/smtpd_sasl_glue.c @@ -120,6 +120,10 @@ /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA /*--*/ /* System library. */ diff --git a/src/smtpd/smtpd_state.c b/src/smtpd/smtpd_state.c index f2f5f89..fefc543 100644 --- a/src/smtpd/smtpd_state.c +++ b/src/smtpd/smtpd_state.c @@ -135,6 +135,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream, state->instance = vstring_alloc(10); state->seqno = 0; state->rewrite_context = 0; + state->notes = 0; #if 0 state->ehlo_discard_mask = ~0; #else diff --git a/src/smtpstone/smtp-source.c b/src/smtpstone/smtp-source.c index be388d6..f9fa64f 100644 --- a/src/smtpstone/smtp-source.c +++ b/src/smtpstone/smtp-source.c @@ -42,7 +42,7 @@ /* Don't disconnect after sending a message; send the next /* message over the same connection. /* .IP "\fB-f \fIfrom\fR" -/* Use the specified sender address (default: ). +/* Use the specified sender address (default: ). /* .IP "\fB-F \fIfile\fR" /* Send the pre-formatted message header and body in the /* specified \fIfile\fR, while prepending '.' before lines that @@ -54,31 +54,49 @@ /* Speak LMTP rather than SMTP. /* .IP "\fB-m \fImessage_count\fR" /* Send the specified number of messages (default: 1). -/* .IP "\fB-M \fImyhostname\fR" +/* .IP "\fB-M \fImy-hostname\fR" /* Use the specified hostname or [address] in the HELO command /* and in the default sender and recipient addresses, instead /* of the machine hostname. /* .IP "\fB-N\fR" -/* Prepend a non-repeating sequence number to each recipient -/* address. This avoids the artificial 100% hit rate in the -/* resolve and rewrite client caches and exercises the -/* trivial-rewrite daemon, better approximating Postfix -/* performance under real-life work-loads. +/* Generate each recipient address by appending a number (a +/* per-process recipient counter) to the recipient address +/* localpart specified with the \fB-t\fR option. +/* +/* Note: to use the number as an address extension, specify +/* an explicit address delimiter at the end of the recipient +/* localpart, as in "\fB-t localpart+@domain\fR" or "\fB-t +/* localpart+\fR", where "\fB+\fR" is a Postfix recipient +/* address delimiter. +/* +/* Benefits: +/* .RS +/* .IP \(bu +/* A non-constant recipient address avoids an unrealistic 100% +/* cache hit rate in clients of the Postfix trivial-rewrite +/* service, better approximating performance under real-life +/* work-loads. +/* .IP \(bu +/* A fixed recipient address local-part with a non-constant +/* address extension avoids the need to configure a large +/* number of valid recipient addresses in the receiving Postfix +/* server. +/* .RE /* .IP \fB-o\fR /* Old mode: don't send HELO, and don't send message headers. /* .IP "\fB-r \fIrecipient_count\fR" -/* Send the specified number of recipients per transaction (default: 1). -/* Recipient names are generated by prepending a number to the -/* recipient address. +/* Send the specified number of recipients per transaction +/* (default: 1), and generate recipient addresses as described +/* under the \fB-N\fR option. /* .IP "\fB-R \fIinterval\fR" -/* Wait for a random period of time 0 <= n <= interval between messages. +/* Wait a random time (0 <= n <= \fIinterval\fR) between messages. /* Suspending one thread does not affect other delivery threads. /* .IP "\fB-s \fIsession_count\fR" /* Run the specified number of SMTP sessions in parallel (default: 1). /* .IP "\fB-S \fIsubject\fR" /* Send mail with the named subject line (default: none). /* .IP "\fB-t \fIto\fR" -/* Use the specified recipient address (default: ). +/* Use the specified recipient address (default: ). /* .IP "\fB-T \fIwindowsize\fR" /* Override the default TCP window size. To work around /* broken TCP window scaling implementations, specify a @@ -172,6 +190,7 @@ typedef struct SESSION { int rcpt_done; /* # of recipients done */ int rcpt_count; /* # of recipients to go */ int rcpt_accepted; /* # of recipients accepted */ + int rcpt_sample; /* Sample recipient # for To: header */ VSTREAM *stream; /* open connection */ int connect_count; /* # of connect()s to retry */ struct SESSION *next; /* connect() queue linkage */ @@ -202,7 +221,11 @@ static struct sockaddr *sa; static int sa_length; static int recipients = 1; static char *defaddr; -static char *recipient; +typedef struct { + char *local; + char *at_domain; +} RECIPIENT; +static RECIPIENT *recipient; static char *sender; static char *message_data; static int message_length; @@ -216,7 +239,8 @@ static int random_delay = 0; static int fixed_delay = 0; static int talk_lmtp = 0; static char *subject = 0; -static int number_rcpts = 0; +static int global_rcpt_suffix = 0; +static int global_rcpt_done = 0; static int allow_reject = 0; static void enqueue_connect(SESSION *); @@ -238,6 +262,20 @@ static void send_quit(SESSION *); static void quit_done(int, void *); static void close_session(SESSION *); +/* make_recipient - parse recipient into localpart and at_domain */ + +static RECIPIENT *make_recipient(const char *address) +{ + RECIPIENT *rp = (RECIPIENT *) mymalloc(sizeof(*rp)); + const char *at; + + if ((at = strrchr(address, '@')) == 0) + at = address + strlen(address); + rp->local = mystrndup(address, at - address); + rp->at_domain = mystrdup(at); + return (rp); +} + /* random_interval - generate a random value in 0 .. (small) interval */ static int random_interval(int interval) @@ -655,12 +693,13 @@ static void send_rcpt(int unused_event, void *context) if ((except = vstream_setjmp(session->stream)) != 0) msg_fatal("%s while sending recipient", exception_text(except)); - if (session->rcpt_count > 1 || number_rcpts > 0) - command(session->stream, "RCPT TO:<%d%s>", - number_rcpts ? number_rcpts++ : session->rcpt_count, - recipient); + if (global_rcpt_suffix) + command(session->stream, "RCPT TO:<%s%d%s>", + recipient->local, session->rcpt_sample = global_rcpt_done++, + recipient->at_domain); else - command(session->stream, "RCPT TO:<%s>", recipient); + command(session->stream, "RCPT TO:<%s%s>", + recipient->local, recipient->at_domain); session->rcpt_count--; session->rcpt_done++; @@ -765,10 +804,16 @@ static void data_done(int unused, void *context) mypid = getpid(); } smtp_printf(session->stream, "From: <%s>", sender); - smtp_printf(session->stream, "To: <%s>", recipient); + if (global_rcpt_suffix) + smtp_printf(session->stream, "To: <%s%d%s>", recipient->local, + session->rcpt_sample, recipient->at_domain); + else + smtp_printf(session->stream, "To: <%s%s>", + recipient->local, recipient->at_domain); smtp_printf(session->stream, "Date: %s", mydate); smtp_printf(session->stream, "Message-Id: <%04x.%04x.%04x@%s>", - mypid, vstream_fileno(session->stream), message_count, var_myhostname); + mypid, vstream_fileno(session->stream), message_count, + var_myhostname); if (subject) smtp_printf(session->stream, "Subject: %s", subject); smtp_fputs("", 0, session->stream); @@ -1021,7 +1066,7 @@ int main(int argc, char **argv) var_myhostname = optarg; break; case 'N': - number_rcpts = 1; + global_rcpt_suffix = 1; break; case 'o': send_helo_first = 0; @@ -1030,6 +1075,7 @@ int main(int argc, char **argv) case 'r': if ((recipients = atoi(optarg)) <= 0) msg_fatal("bad recipient count: %s", optarg); + global_rcpt_suffix = 1; break; case 'R': if (fixed_delay > 0) @@ -1045,7 +1091,7 @@ int main(int argc, char **argv) subject = optarg; break; case 't': - recipient = optarg; + recipient = make_recipient(optarg); break; case 'T': if ((inet_windowsize = atoi(optarg)) <= 0) @@ -1160,7 +1206,7 @@ int main(int argc, char **argv) if (sender == 0) sender = defaddr; if (recipient == 0) - recipient = defaddr; + recipient = make_recipient(defaddr); } /* diff --git a/src/tls/tls.h b/src/tls/tls.h index 73eebae..3ec41ba 100644 --- a/src/tls/tls.h +++ b/src/tls/tls.h @@ -78,6 +78,7 @@ extern const char *str_tls_level(int); #include /* OPENSSL_VERSION_NUMBER */ #include #include +#include /* TLS extensions */ /* Appease indent(1) */ #define x509_stack_t STACK_OF(X509) @@ -203,8 +204,8 @@ extern void tls_dane_flush(void); extern TLS_DANE *tls_dane_alloc(void); extern void tls_tlsa_free(TLS_TLSA *); extern void tls_dane_free(TLS_DANE *); -extern void tls_dane_add_fpt_digests(TLS_DANE *, const char *, const char *, - int); +extern void tls_dane_add_fpt_digests(TLS_DANE *, int, const char *, + const char *, int); extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int); extern int tls_dane_load_trustfile(TLS_DANE *, const char *); @@ -232,6 +233,8 @@ typedef struct { const char *kex_name; /* shared key-exchange algorithm */ const char *kex_curve; /* shared key-exchange ECDHE curve */ int kex_bits; /* shared FFDHE key exchange bits */ + int ctos_rpk; /* Did the client send an RPK? */ + int stoc_rpk; /* Did the server send an RPK? */ const char *clnt_sig_name; /* client's signature key algorithm */ const char *clnt_sig_curve; /* client's ECDSA curve name */ int clnt_sig_bits; /* client's RSA signature key bits */ @@ -264,13 +267,17 @@ typedef struct { * Peer status bits. TLS_CERT_FLAG_MATCHED implies TLS_CERT_FLAG_TRUSTED * only in the case of a hostname match. */ -#define TLS_CERT_FLAG_PRESENT (1<<0) +#define TLS_CRED_FLAG_CERT (1<<0) #define TLS_CERT_FLAG_ALTNAME (1<<1) #define TLS_CERT_FLAG_TRUSTED (1<<2) #define TLS_CERT_FLAG_MATCHED (1<<3) #define TLS_CERT_FLAG_SECURED (1<<4) +#define TLS_CRED_FLAG_RPK (1<<5) +#define TLS_CRED_FLAG_ANY (TLS_CRED_FLAG_CERT|TLS_CRED_FLAG_RPK) -#define TLS_CERT_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_PRESENT)) +#define TLS_CRED_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CRED_FLAG_ANY)) +#define TLS_CERT_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CRED_FLAG_CERT)) +#define TLS_RPK_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CRED_FLAG_RPK)) #define TLS_CERT_IS_ALTNAME(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_ALTNAME)) #define TLS_CERT_IS_TRUSTED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_TRUSTED)) #define TLS_CERT_IS_MATCHED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_MATCHED)) @@ -472,6 +479,7 @@ typedef struct { VSTREAM *stream; int fd; /* Event-driven file descriptor */ int timeout; + int enable_rpk; /* Solicit server raw public keys */ int tls_level; /* Security level */ const char *nexthop; /* destination domain */ const char *host; /* MX hostname */ @@ -508,12 +516,12 @@ extern TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *, a6, a7, a8, a9, a10, a11, a12, a13, a14)) #define TLS_CLIENT_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ - a10, a11, a12, a13, a14, a15, a16, a17) \ + a10, a11, a12, a13, a14, a15, a16, a17, a18) \ tls_client_start((((props)->a1), ((props)->a2), ((props)->a3), \ ((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \ ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \ ((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15), \ - ((props)->a16), ((props)->a17), (props))) + ((props)->a16), ((props)->a17), ((props)->a18), (props))) /* * tls_server.c @@ -546,6 +554,7 @@ typedef struct { VSTREAM *stream; /* Client stream */ int fd; /* Event-driven file descriptor */ int timeout; /* TLS handshake timeout */ + int enable_rpk; /* Solicit client raw public keys */ int requirecert; /* Insist on client cert? */ const char *serverid; /* Server instance (salt cache key) */ const char *namaddr; /* Client nam[addr] for logging */ @@ -570,10 +579,12 @@ extern TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *); ((props)->a16), ((props)->a17), ((props)->a18), ((props)->a19), \ ((props)->a20), (props))) -#define TLS_SERVER_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ +#define TLS_SERVER_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ + a10, a11) \ tls_server_start((((props)->a1), ((props)->a2), ((props)->a3), \ ((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \ - ((props)->a8), ((props)->a9), ((props)->a10), (props))) + ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \ + (props))) /* * tls_session.c @@ -660,7 +671,7 @@ extern TLS_TLSA *tlsa_prepend(TLS_TLSA *, uint8_t, uint8_t, uint8_t, extern const EVP_MD *tls_digest_byname(const char *, EVP_MD_CTX **); extern char *tls_digest_encode(const unsigned char *, int); extern char *tls_cert_fprint(X509 *, const char *); -extern char *tls_pkey_fprint(X509 *, const char *); +extern char *tls_pkey_fprint(EVP_PKEY *, const char *); extern char *tls_serverid_digest(TLS_SESS_STATE *, const TLS_CLIENT_START_PROPS *, const char *); @@ -696,6 +707,8 @@ extern long tls_bio_dump_cb(BIO *, int, const char *, int, long, long); #endif extern const EVP_MD *tls_validate_digest(const char *); +extern void tls_enable_client_rpk(SSL_CTX *, SSL *); +extern void tls_enable_server_rpk(SSL_CTX *, SSL *); /* * tls_seed.c diff --git a/src/tls/tls_client.c b/src/tls/tls_client.c index e0dfe15..3eda859 100644 --- a/src/tls/tls_client.c +++ b/src/tls/tls_client.c @@ -86,8 +86,9 @@ /* available as: /* .IP TLScontext->peer_status /* A bitmask field that records the status of the peer certificate -/* verification. This consists of one or more of TLS_CERT_FLAG_PRESENT, -/* TLS_CERT_FLAG_TRUSTED, TLS_CERT_FLAG_MATCHED and TLS_CERT_FLAG_SECURED. +/* verification. This consists of one or more of TLS_CRED_FLAG_CERT, +/* TLS_CRED_FLAG_RPK, TLS_CERT_FLAG_TRUSTED, TLS_CERT_FLAG_MATCHED and +/* TLS_CERT_FLAG_SECURED. /* .IP TLScontext->peer_CN /* Extracted CommonName of the peer, or zero-length string if the /* information could not be extracted. @@ -303,15 +304,11 @@ static void uncache_session(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext) tls_mgr_delete(TLScontext->cache_type, TLScontext->serverid); } -/* verify_extract_name - verify peer name and extract peer information */ +/* verify_x509 - process X.509 certificate verification status */ -static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert, - const TLS_CLIENT_START_PROPS *props) +static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert, + const TLS_CLIENT_START_PROPS *props) { - int verbose; - - verbose = TLScontext->log_mask & - (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT); /* * On exit both peer_CN and issuer_CN should be set. @@ -345,7 +342,8 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert, TLScontext->peer_status |= TLS_CERT_FLAG_SECURED; TLScontext->peer_status |= TLS_CERT_FLAG_MATCHED; - if (verbose) { + if (TLScontext->log_mask & + (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) { const char *peername = SSL_get0_peername(TLScontext->con); if (peername) @@ -356,6 +354,50 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert, } } + /* + * Give them a clue. Problems with trust chain verification are logged + * when the session is first negotiated, before the session is stored + * into the cache. We don't want mystery failures, so log the fact the + * real problem is to be found in the past. + */ + if (!TLS_CERT_IS_MATCHED(TLScontext) + && (TLScontext->log_mask & TLS_LOG_UNTRUSTED)) { + if (TLScontext->session_reused == 0) + tls_log_verify_error(TLScontext); + else + msg_info("%s: re-using session with untrusted peer credential, " + "look for details earlier in the log", props->namaddr); + } +} + +/* verify_rpk - process RFC7250 raw public key verification status */ + +static void verify_rpk(TLS_SESS_STATE *TLScontext, EVP_PKEY *peerpkey, + const TLS_CLIENT_START_PROPS *props) +{ + /* Was the raw public key (type of cert) matched? */ + if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) { + TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED; + if (TLScontext->must_fail) { + msg_panic("%s: raw public key valid despite trust init failure", + TLScontext->namaddr); + } else if (TLS_MUST_MATCH(TLScontext->level)) { + + /* + * Fully secured only if not insecure like half-dane. We use + * TLS_CERT_FLAG_MATCHED to satisfy policy, but + * TLS_CERT_FLAG_SECURED to log the effective security. + */ + if (!TLS_NEVER_SECURED(TLScontext->level)) + TLScontext->peer_status |= TLS_CERT_FLAG_SECURED; + TLScontext->peer_status |= TLS_CERT_FLAG_MATCHED; + + if (TLScontext->log_mask & + (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) + tls_dane_log(TLScontext); + } + } + /* * Give them a clue. Problems with trust chain verification are logged * when the session is first negotiated, before the session is stored @@ -792,6 +834,30 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) return (0); } + /* + * Enable support for client->server raw public keys, provided we actually + * have keys to send. They'll only be used if the server also enables + * client RPKs. + * + * XXX: When the server requests client auth, the TLS 1.2 protocol does not + * provide an unambiguous mechanism for the client to not send an RPK (as + * it can with client X.509 certs or TLS 1.3). This is why we don't just + * enable client RPK also with no keys in hand. + * + * A very unlikely scenario is that the server allows clients to not send + * keys, but only accepts keys for a set of algorithms we don't have. Then + * we still can't send a key, but have agreed to RPK. OpenSSL will attempt + * to send an empty RPK even with TLS 1.2 (and will accept such a message), + * but other implementations may be more strict. + * + * We could limit client RPK support to connections that support only TLS + * 1.3 and up, but that's practical only decades in the future, and the + * risk scenario is contrived and very unlikely. + */ + if (SSL_CTX_get0_certificate(client_ctx) != NULL && + SSL_CTX_get0_privatekey(client_ctx) != NULL) + tls_enable_client_rpk(client_ctx, NULL); + /* * With OpenSSL 1.0.2 and later the client EECDH curve list becomes * configurable with the preferred curve negotiated via the supported @@ -1007,6 +1073,24 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) return (0); } + /* + * Possibly enable RFC7250 raw public keys in non-DANE/non-PKI levels + * when the fingerprint mask includes only public keys. For "may" and + * "encrypt" this is a heuristic, since we don't use the fingerprints + * beyond reporting them in verbose logging. If you always want certs + * with "may" and "encrypt" you'll have to tolerate them with + * "fingerprint", or use a separate transport. + */ + switch (props->tls_level) { + case TLS_LEV_MAY: + case TLS_LEV_ENCRYPT: + case TLS_LEV_FPRINT: + if (props->enable_rpk) + tls_enable_server_rpk(NULL, TLScontext->con); + default: + break; + } + /* * Try to convey the configured TLSA records for this connection to the * OpenSSL library. If none are "usable", we'll fall back to "encrypt" @@ -1175,6 +1259,7 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext, { const SSL_CIPHER *cipher; X509 *peercert; + EVP_PKEY *peerpkey = 0; /* Turn off packet dump if only dumping the handshake */ if ((TLScontext->log_mask & TLS_LOG_ALLPKTS) == 0) @@ -1192,31 +1277,61 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext, * Do peername verification if requested and extract useful information * from the certificate for later use. */ - if ((peercert = TLS_PEEK_PEER_CERT(TLScontext->con)) != 0) { - TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT; + peercert = TLS_PEEK_PEER_CERT(TLScontext->con); + if (peercert != 0) { + peerpkey = X509_get0_pubkey(peercert); + } +#if OPENSSL_VERSION_PREREQ(3,2) + else { + peerpkey = SSL_get0_peer_rpk(TLScontext->con); + } +#endif + + if (peercert != 0) { + TLScontext->peer_status |= TLS_CRED_FLAG_CERT; /* * Peer name or fingerprint verification as requested. * Unconditionally set peer_CN, issuer_CN and peer_cert_fprint. Check * fingerprint first, and avoid logging verified as untrusted in the - * call to verify_extract_name(). + * call to verify_x509(). */ - TLScontext->peer_cert_fprint = tls_cert_fprint(peercert, props->mdalg); - TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->mdalg); - verify_extract_name(TLScontext, peercert, props); + TLScontext->peer_cert_fprint = + tls_cert_fprint(peercert, props->mdalg); + TLScontext->peer_pkey_fprint = + tls_pkey_fprint(peerpkey, props->mdalg); + verify_x509(TLScontext, peercert, props); if (TLScontext->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) - msg_info("%s: subject_CN=%s, issuer_CN=%s, " - "fingerprint=%s, pkey_fingerprint=%s", props->namaddr, + msg_info("%s: subject_CN=%s, issuer=%s%s%s%s%s", + TLScontext->namaddr, TLScontext->peer_CN, TLScontext->issuer_CN, - TLScontext->peer_cert_fprint, - TLScontext->peer_pkey_fprint); + *TLScontext->peer_cert_fprint ? + ", cert fingerprint=" : "", + *TLScontext->peer_cert_fprint ? + TLScontext->peer_cert_fprint : "", + *TLScontext->peer_pkey_fprint ? + ", pkey fingerprint=" : "", + *TLScontext->peer_pkey_fprint ? + TLScontext->peer_pkey_fprint : ""); } else { TLScontext->issuer_CN = mystrdup(""); TLScontext->peer_CN = mystrdup(""); TLScontext->peer_cert_fprint = mystrdup(""); - TLScontext->peer_pkey_fprint = mystrdup(""); + + if (!peerpkey) { + TLScontext->peer_pkey_fprint = mystrdup(""); + } else { + TLScontext->peer_status |= TLS_CRED_FLAG_RPK; + TLScontext->peer_pkey_fprint = + tls_pkey_fprint(peerpkey, props->mdalg); + if (TLScontext->log_mask & + (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) + msg_info("%s: raw public key fingerprint=%s", props->namaddr, + TLScontext->peer_pkey_fprint); + verify_rpk(TLScontext, peerpkey, props); + } } /* diff --git a/src/tls/tls_dane.c b/src/tls/tls_dane.c index a2b9b80..ac7f05f 100644 --- a/src/tls/tls_dane.c +++ b/src/tls/tls_dane.c @@ -22,8 +22,9 @@ /* void tls_dane_free(dane) /* TLS_DANE *dane; /* -/* void tls_dane_add_fpt_digests(dane, digest, delim, smtp_mode) +/* void tls_dane_add_fpt_digests(dane, pkey_only, digest, delim, smtp_mode) /* TLS_DANE *dane; +/* int pkey_only; /* const char *digest; /* const char *delim; /* int smtp_mode; @@ -130,6 +131,9 @@ /* SSL context to be configured with the chosen digest algorithms. /* .IP fpt_alg /* The OpenSSL EVP digest algorithm handle for the fingerprint digest. +/* .IP pkey_only +/* When true, generate "fingerprint" TLSA records for just the public +/* keys. Otherwise, for both certificates and public keys. /* .IP tlsa /* TLSA record linked list head, initially NULL. /* .IP usage @@ -415,8 +419,9 @@ static void dane_free(void *dane, void *unused_context) /* tls_dane_add_fpt_digests - map fingerprint list to DANE TLSA RRset */ -void tls_dane_add_fpt_digests(TLS_DANE *dane, const char *digest, - const char *delim, int smtp_mode) +void tls_dane_add_fpt_digests(TLS_DANE *dane, int pkey_only, + const char *digest, const char *delim, + int smtp_mode) { ARGV *values = argv_split(digest, delim); ssize_t i; @@ -455,31 +460,41 @@ void tls_dane_add_fpt_digests(TLS_DANE *dane, const char *digest, continue; } +#define USTR_LEN(raw) (unsigned char *) STR(raw), VSTRING_LEN(raw) + /* * At the "fingerprint" security level certificate digests and public - * key digests are interchangeable. Each leaf certificate is matched - * via either the public key digest or full certificate digest. The - * DER encoding of a certificate is not a valid public key, and - * conversely, the DER encoding of a public key is not a valid - * certificate. An attacker would need a 2nd-preimage that is + * key digests are by default interchangeable. Each leaf certificate + * is matched via either the public key digest or full certificate + * digest. The DER encoding of a certificate is not a valid public + * key, and conversely, the DER encoding of a public key is not a + * valid certificate. An attacker would need a 2nd-preimage that is * feasible across types (given cert digest == some pkey digest) and * yet presumably difficult within a type (e.g. given cert digest == * some other cert digest). No such attacks are known at this time, * and it is expected that if any are found they would work within as * well as across the cert/pkey data types. + * + * That said, when `pkey_only` is true, we match only public keys. * * The private-use matching type "255" is mapped to the configured * fingerprint digest, which may (harmlessly) coincide with one of * the standard DANE digest algorithms. The private code point is * however unconditionally enabled. */ + if (!pkey_only) { + dane->tlsa = tlsa_prepend(dane->tlsa, 3, 0, 255, USTR_LEN(raw)); + if (log_mask & (TLS_LOG_VERBOSE | TLS_LOG_DANE)) + tlsa_info("fingerprint", "digest as private-use TLSA record", + 3, 0, 255, USTR_LEN(raw)); + } + + /* The public key match is unconditional */ + dane->tlsa = tlsa_prepend(dane->tlsa, 3, 1, 255, USTR_LEN(raw)); if (log_mask & (TLS_LOG_VERBOSE | TLS_LOG_DANE)) tlsa_info("fingerprint", "digest as private-use TLSA record", - 3, 0, 255, (unsigned char *) STR(raw), VSTRING_LEN(raw)); - dane->tlsa = tlsa_prepend(dane->tlsa, 3, 0, 255, - (unsigned char *) STR(raw), VSTRING_LEN(raw)); - dane->tlsa = tlsa_prepend(dane->tlsa, 3, 1, 255, - (unsigned char *) STR(raw), VSTRING_LEN(raw)); + 3, 1, 255, USTR_LEN(raw)); + vstring_free(raw); } argv_free(values); @@ -798,12 +813,21 @@ int tls_dane_enable(TLS_SESS_STATE *TLScontext) SSL *ssl = TLScontext->con; int usable = 0; int ret; + int rpk_compat = 1; for (tp = dane->tlsa; tp != 0; tp = tp->next) { ret = SSL_dane_tlsa_add(ssl, tp->usage, tp->selector, tp->mtype, tp->data, tp->length); if (ret > 0) { ++usable; + /* + * Disable use of RFC7250 raw public keys if any TLSA record + * depends on X.509 certificates. Only DANE-EE(3) SPKI(1) records + * can get by with just a public key. + */ + if (tp->usage != DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE + || tp->selector != DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO) + rpk_compat = 0; continue; } if (ret == 0) { @@ -818,6 +842,9 @@ int tls_dane_enable(TLS_SESS_STATE *TLScontext) tls_print_errors(); return (-1); } + if (rpk_compat) + tls_enable_server_rpk(NULL, ssl); + return (usable); } @@ -964,8 +991,9 @@ void tls_dane_log(TLS_SESS_STATE *TLScontext) { static VSTRING *top; static VSTRING *bot; + X509 *mcert = 0; EVP_PKEY *mspki = 0; - int depth = SSL_get0_dane_authority(TLScontext->con, NULL, &mspki); + int depth = SSL_get0_dane_authority(TLScontext->con, &mcert, &mspki); uint8_t u, s, m; unsigned const char *data; size_t dlen; @@ -994,22 +1022,27 @@ void tls_dane_log(TLS_SESS_STATE *TLScontext) hex_encode(top, (char *) data, dlen); } - switch (TLScontext->level) { - case TLS_LEV_FPRINT: + if (TLScontext->level == TLS_LEV_FPRINT) { msg_info("%s: Matched fingerprint: %s%s%s", TLScontext->namaddr, STR(top), dlen > MAX_DUMP_BYTES ? "..." : "", dlen > MAX_DUMP_BYTES ? STR(bot) : ""); return; - - default: - msg_info("%s: Matched DANE %s at depth %d: %u %u %u %s%s%s", - TLScontext->namaddr, mspki ? - "TA public key verified certificate" : depth ? - "TA certificate" : "EE certificate", depth, u, s, m, + } +#if OPENSSL_VERSION_PREREQ(3,2) + if (SSL_get0_peer_rpk(TLScontext->con) != NULL) { + msg_info("%s: Matched DANE raw public key: %u %u %u %s%s%s", + TLScontext->namaddr, u, s, m, STR(top), dlen > MAX_DUMP_BYTES ? "..." : "", dlen > MAX_DUMP_BYTES ? STR(bot) : ""); return; } +#endif + msg_info("%s: Matched DANE %s at depth %d: %u %u %u %s%s%s", + TLScontext->namaddr, mspki ? + "TA public key verified certificate" : depth ? + "TA certificate" : "EE certificate", depth, u, s, m, + STR(top), dlen > MAX_DUMP_BYTES ? "..." : "", + dlen > MAX_DUMP_BYTES ? STR(bot) : ""); } #ifdef TEST diff --git a/src/tls/tls_fprint.c b/src/tls/tls_fprint.c index 39b5a52..dc3f99e 100644 --- a/src/tls/tls_fprint.c +++ b/src/tls/tls_fprint.c @@ -24,7 +24,7 @@ /* const char *mdalg; /* /* char *tls_pkey_fprint(peercert, mdalg) -/* X509 *peercert; +/* EVP_PKEY *peerpkey; /* const char *mdalg; /* DESCRIPTION /* tls_digest_byname() constructs, and optionally returns, an EVP_MD_CTX @@ -48,8 +48,6 @@ /* /* tls_pkey_fprint() returns a public-key fingerprint; in all /* other respects the function behaves as tls_cert_fprint(). -/* The var_tls_bc_pkey_fprint variable enables an incorrect -/* algorithm that was used in Postfix versions 2.9.[0-5]. /* The return value is dynamically allocated with mymalloc(), /* and the caller must eventually free it with myfree(). /* @@ -274,6 +272,9 @@ char *tls_serverid_digest(TLS_SESS_STATE *TLScontext, CHECK_OK_AND_DIGEST_CHARS(mdctx, props->protocols); CHECK_OK_AND_DIGEST_CHARS(mdctx, ciphers); + /* Just in case we make this destination-policy specific */ + CHECK_OK_AND_DIGEST_OBJECT(mdctx, &props->enable_rpk); + /* * Ensure separation of caches for sessions where DANE trust * configuration succeeded from those where it did not. The latter @@ -398,38 +399,24 @@ char *tls_cert_fprint(X509 *peercert, const char *mdalg) return (result); } -/* tls_pkey_fprint - extract public key fingerprint from certificate */ +/* tls_pkey_fprint - extract public key fingerprint */ -char *tls_pkey_fprint(X509 *peercert, const char *mdalg) +char *tls_pkey_fprint(EVP_PKEY *peerpkey, const char *mdalg) { - if (var_tls_bc_pkey_fprint) { - const char *myname = "tls_pkey_fprint"; - ASN1_BIT_STRING *key; - char *result; - - key = X509_get0_pubkey_bitstr(peercert); - if (key == 0) - msg_fatal("%s: error extracting legacy public-key fingerprint: %m", - myname); - - result = tls_data_fprint(key->data, key->length, mdalg); - return (result); - } else { - int len; - unsigned char *buf; - unsigned char *buf2; - char *result; - - len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), NULL); - buf2 = buf = mymalloc(len); - i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), &buf2); - if (buf2 - buf != len) - msg_panic("i2d_X509_PUBKEY invalid result length"); - - result = tls_data_fprint(buf, len, mdalg); - myfree(buf); - return (result); - } + int len; + unsigned char *buf; + unsigned char *buf2; + char *result; + + len = i2d_PUBKEY(peerpkey, NULL); + buf2 = buf = mymalloc(len); + i2d_PUBKEY(peerpkey, &buf2); + if (buf2 - buf != len) + msg_panic("i2d_PUBKEY invalid result length"); + + result = tls_data_fprint(buf, len, mdalg); + myfree(buf); + return (result); } #endif diff --git a/src/tls/tls_misc.c b/src/tls/tls_misc.c index b7acd1d..cf8f6fa 100644 --- a/src/tls/tls_misc.c +++ b/src/tls/tls_misc.c @@ -118,6 +118,14 @@ /* /* const EVP_MD *tls_validate_digest(dgst) /* const char *dgst; +/* +/* void tls_enable_client_rpk(ctx, ssl) +/* SSL_CTX *ctx; +/* SSL *ssl; +/* +/* void tls_enable_server_rpk(ctx, ssl) +/* SSL_CTX *ctx; +/* SSL *ssl; /* DESCRIPTION /* This module implements public and internal routines that /* support the TLS client and server. @@ -215,6 +223,12 @@ /* /* tls_validate_digest() returns a static handle for the named /* digest algorithm, or NULL on error. +/* +/* tls_enable_client_rpk() enables the use of raw public keys in the +/* client to server direction, if supported by the OpenSSL library. +/* +/* tls_enable_server_rpk() enables the use of raw public keys in the +/* server to client direction, if supported by the OpenSSL library. /* LICENSE /* .ad /* .fi @@ -762,7 +776,7 @@ int tls_library_init(void) /* * The default global config file is optional. With "default" - * initialisation we don't insist on a match for the requested + * initialization we don't insist on a match for the requested * application name, allowing fallback to the default application * name, even when a non-default application name is specified. * Errors in loading the default configuration are ignored. @@ -1028,7 +1042,6 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext) SSL *ssl = TLScontext->con; int srvr = SSL_is_server(ssl); EVP_PKEY *dh_pkey = 0; - X509 *local_cert; EVP_PKEY *local_pkey = 0; X509 *peer_cert; EVP_PKEY *peer_pkey = 0; @@ -1060,18 +1073,23 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext) } /* - * On the client end, the certificate may be preset, but not used, so we + * On the client end, the certificate may be present, but not used, so we * check via SSL_get_signature_nid(). This means that local signature * data on clients requires at least 1.1.1a. */ - if (srvr || SSL_get_signature_nid(ssl, &nid)) - local_cert = SSL_get_certificate(ssl); - else - local_cert = 0; - + if (srvr || SSL_get_signature_nid(ssl, &nid)) { + local_pkey = SSL_get_privatekey(ssl); + } /* Signature algorithms for the local end of the connection */ - if (local_cert) { - local_pkey = X509_get0_pubkey(local_cert); + if (local_pkey) { +#if OPENSSL_VERSION_PREREQ(3,2) + if (srvr) + TLScontext->stoc_rpk = TLSEXT_cert_type_rpk == + SSL_get_negotiated_server_cert_type(ssl); + else + TLScontext->ctos_rpk = TLSEXT_cert_type_rpk == + SSL_get_negotiated_client_cert_type(ssl); +#endif /* * Override the built-in name for the "ECDSA" algorithms OID, with @@ -1097,7 +1115,6 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext) break; #endif } - /* No X509_free(local_cert) */ } /* @@ -1107,9 +1124,26 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext) if (SSL_get_signature_nid(ssl, &nid) && nid != NID_undef) locl_sig_dgst = OBJ_nid2sn(nid); } - /* Signature algorithms for the peer end of the connection */ - if ((peer_cert = TLS_PEEK_PEER_CERT(ssl)) != 0) { + peer_cert = TLS_PEEK_PEER_CERT(ssl); + if (peer_cert != 0) { peer_pkey = X509_get0_pubkey(peer_cert); + } +#if OPENSSL_VERSION_PREREQ(3,2) + else { + peer_pkey = SSL_get0_peer_rpk(ssl); + } +#endif + + /* Signature algorithms for the peer end of the connection */ + if (peer_pkey != 0) { +#if OPENSSL_VERSION_PREREQ(3,2) + if (srvr) + TLScontext->ctos_rpk = TLSEXT_cert_type_rpk == + SSL_get_negotiated_client_cert_type(ssl); + else + TLScontext->stoc_rpk = TLSEXT_cert_type_rpk == + SSL_get_negotiated_server_cert_type(ssl); +#endif /* * Override the built-in name for the "ECDSA" algorithms OID, with @@ -1144,8 +1178,9 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext) if (SSL_get_peer_signature_nid(ssl, &nid) && nid != NID_undef) peer_sig_dgst = OBJ_nid2sn(nid); - TLS_FREE_PEER_CERT(peer_cert); } + TLS_FREE_PEER_CERT(peer_cert); + if (kex_name) { TLScontext->kex_name = mystrdup(kex_name); TLScontext->kex_curve = kex_curve; @@ -1180,7 +1215,7 @@ void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx) */ vstring_sprintf(msg, "%s TLS connection %s %s %s%s%s: %s" " with cipher %s (%d/%d bits)", - !TLS_CERT_IS_PRESENT(ctx) ? "Anonymous" : + !TLS_CRED_IS_PRESENT(ctx) ? "Anonymous" : TLS_CERT_IS_SECURED(ctx) ? "Verified" : TLS_CERT_IS_TRUSTED(ctx) ? "Trusted" : "Untrusted", usage == TLS_USAGE_NEW ? "established" : "reused", @@ -1199,9 +1234,13 @@ void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx) vstring_sprintf_append(msg, " server-signature %s", ctx->srvr_sig_name); if (ctx->srvr_sig_curve && *ctx->srvr_sig_curve) - vstring_sprintf_append(msg, " (%s)", ctx->srvr_sig_curve); + vstring_sprintf_append(msg, " (%s%s)", ctx->srvr_sig_curve, + ctx->stoc_rpk ? " raw public key" : ""); else if (ctx->srvr_sig_bits > 0) - vstring_sprintf_append(msg, " (%d bits)", ctx->srvr_sig_bits); + vstring_sprintf_append(msg, " (%d bit%s)", ctx->srvr_sig_bits, + ctx->stoc_rpk ? " raw public key" : "s"); + else if (ctx->stoc_rpk) + vstring_sprintf_append(msg, " (raw public key)"); if (ctx->srvr_sig_dgst && *ctx->srvr_sig_dgst) vstring_sprintf_append(msg, " server-digest %s", ctx->srvr_sig_dgst); @@ -1210,9 +1249,13 @@ void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx) vstring_sprintf_append(msg, " client-signature %s", ctx->clnt_sig_name); if (ctx->clnt_sig_curve && *ctx->clnt_sig_curve) - vstring_sprintf_append(msg, " (%s)", ctx->clnt_sig_curve); + vstring_sprintf_append(msg, " (%s%s)", ctx->clnt_sig_curve, + ctx->ctos_rpk ? " raw public key" : ""); else if (ctx->clnt_sig_bits > 0) - vstring_sprintf_append(msg, " (%d bits)", ctx->clnt_sig_bits); + vstring_sprintf_append(msg, " (%d bit%s)", ctx->clnt_sig_bits, + ctx->ctos_rpk ? " raw public key" : "s"); + else if (ctx->ctos_rpk) + vstring_sprintf_append(msg, " (raw public key)"); if (ctx->clnt_sig_dgst && *ctx->clnt_sig_dgst) vstring_sprintf_append(msg, " client-digest %s", ctx->clnt_sig_dgst); @@ -1288,6 +1331,8 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr) TLScontext->cipher_name = 0; TLScontext->kex_name = 0; TLScontext->kex_curve = 0; + TLScontext->ctos_rpk = 0; + TLScontext->stoc_rpk = 0; TLScontext->clnt_sig_name = 0; TLScontext->clnt_sig_curve = 0; TLScontext->clnt_sig_dgst = 0; @@ -1702,6 +1747,52 @@ const EVP_MD *tls_validate_digest(const char *dgst) return md_alg; } +void tls_enable_client_rpk(SSL_CTX *ctx, SSL *ssl) +{ +#if OPENSSL_VERSION_PREREQ(3,2) + static int warned = 0; + static const unsigned char cert_types_rpk[] = { + TLSEXT_cert_type_rpk, + TLSEXT_cert_type_x509 + }; + + if ((ctx && !SSL_CTX_set1_client_cert_type(ctx, cert_types_rpk, + sizeof(cert_types_rpk))) || + (ssl && !SSL_set1_client_cert_type(ssl, cert_types_rpk, + sizeof(cert_types_rpk)))) { + if (warned++) { + ERR_clear_error(); + return; + } + msg_warn("Failed to enable client to server raw public key support"); + tls_print_errors(); + } +#endif +} + +void tls_enable_server_rpk(SSL_CTX *ctx, SSL *ssl) +{ +#if OPENSSL_VERSION_PREREQ(3,2) + static int warned = 0; + static const unsigned char cert_types_rpk[] = { + TLSEXT_cert_type_rpk, + TLSEXT_cert_type_x509 + }; + + if ((ctx && !SSL_CTX_set1_server_cert_type(ctx, cert_types_rpk, + sizeof(cert_types_rpk))) || + (ssl && !SSL_set1_server_cert_type(ssl, cert_types_rpk, + sizeof(cert_types_rpk)))) { + if (warned++) { + ERR_clear_error(); + return; + } + msg_warn("Failed to enable server to client raw public key support"); + tls_print_errors(); + } +#endif +} + #else /* diff --git a/src/tls/tls_proxy.h b/src/tls/tls_proxy.h index ca664c6..6528639 100644 --- a/src/tls/tls_proxy.h +++ b/src/tls/tls_proxy.h @@ -32,8 +32,10 @@ #ifdef USE_TLS /* - * TLS_CLIENT_PARAMS structure. If this changes, update all - * TLS_CLIENT_PARAMS related functions in tls_proxy_client_*.c. + * TLS_CLIENT_PARAMS structure, to communicate global TLS library settings + * that are the same for all TLS client contexts. This information is used + * in tlsproxy(8) to detect inconsistencies. If this structure is changed, + * update all TLS_CLIENT_PARAMS related functions in tls_proxy_client_*.c. * * In the serialization these attributes are identified by their configuration * parameter names. @@ -106,11 +108,11 @@ extern VSTREAM *tls_proxy_open(const char *, int, VSTREAM *, const char *, ((props)->a12), ((props)->a13), ((props)->a14)) #define TLS_PROXY_CLIENT_START_PROPS(props, a1, a2, a3, a4, a5, a6, a7, a8, \ - a9, a10, a11, a12, a13, a14) \ + a9, a10, a11, a12, a13, a14, a15) \ (((props)->a1), ((props)->a2), ((props)->a3), \ ((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \ ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \ - ((props)->a12), ((props)->a13), ((props)->a14)) + ((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15)) extern TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *); extern void tls_proxy_context_free(TLS_SESS_STATE *); @@ -168,6 +170,8 @@ extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *); #define TLS_ATTR_KEX_NAME "key_exchange" #define TLS_ATTR_KEX_CURVE "key_exchange_curve" #define TLS_ATTR_KEX_BITS "key_exchange_bits" +#define TLS_ATTR_CTOS_RPK "ctos_rpk" +#define TLS_ATTR_STOC_RPK "stoc_rpk" #define TLS_ATTR_CLNT_SIG_NAME "clnt_signature" #define TLS_ATTR_CLNT_SIG_CURVE "clnt_signature_curve" #define TLS_ATTR_CLNT_SIG_BITS "clnt_signature_bits" @@ -237,6 +241,7 @@ extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *); * TLS_CLIENT_START_PROPS attributes. */ #define TLS_ATTR_TIMEOUT "timeout" +#define TLS_ATTR_ENABLE_RPK "enable_rpk" #define TLS_ATTR_TLS_LEVEL "tls_level" #define TLS_ATTR_NEXTHOP "nexthop" #define TLS_ATTR_HOST "host" diff --git a/src/tls/tls_proxy_client_print.c b/src/tls/tls_proxy_client_print.c index 1cc5778..81e50b9 100644 --- a/src/tls/tls_proxy_client_print.c +++ b/src/tls/tls_proxy_client_print.c @@ -257,6 +257,7 @@ int tls_proxy_client_start_print(ATTR_PRINT_COMMON_FN print_fn, ret = print_fn(fp, flags | ATTR_FLAG_MORE, SEND_ATTR_INT(TLS_ATTR_TIMEOUT, props->timeout), + SEND_ATTR_INT(TLS_ATTR_ENABLE_RPK, props->enable_rpk), SEND_ATTR_INT(TLS_ATTR_TLS_LEVEL, props->tls_level), SEND_ATTR_STR(TLS_ATTR_NEXTHOP, STRING_OR_EMPTY(props->nexthop)), diff --git a/src/tls/tls_proxy_client_scan.c b/src/tls/tls_proxy_client_scan.c index a69388c..d36cf4d 100644 --- a/src/tls/tls_proxy_client_scan.c +++ b/src/tls/tls_proxy_client_scan.c @@ -451,6 +451,7 @@ int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, props->dane = 0; /* scan_fn may return early */ ret = scan_fn(fp, flags | ATTR_FLAG_MORE, RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout), + RECV_ATTR_INT(TLS_ATTR_ENABLE_RPK, &props->enable_rpk), RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level), RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop), RECV_ATTR_STR(TLS_ATTR_HOST, host), @@ -478,7 +479,7 @@ int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, props->cipher_grade = vstring_export(cipher_grade); props->cipher_exclusions = vstring_export(cipher_exclusions); props->mdalg = vstring_export(mdalg); - ret = (ret == 14 ? 1 : -1); + ret = (ret == 15 ? 1 : -1); if (ret != 1) { tls_proxy_client_start_free(props); props = 0; diff --git a/src/tls/tls_proxy_context_print.c b/src/tls/tls_proxy_context_print.c index 04123cb..930410a 100644 --- a/src/tls/tls_proxy_context_print.c +++ b/src/tls/tls_proxy_context_print.c @@ -88,6 +88,10 @@ int tls_proxy_context_print(ATTR_PRINT_COMMON_FN print_fn, VSTREAM *fp, STRING_OR_EMPTY(tp->kex_curve)), SEND_ATTR_INT(TLS_ATTR_KEX_BITS, tp->kex_bits), + SEND_ATTR_INT(TLS_ATTR_CTOS_RPK, + tp->ctos_rpk), + SEND_ATTR_INT(TLS_ATTR_STOC_RPK, + tp->stoc_rpk), SEND_ATTR_STR(TLS_ATTR_CLNT_SIG_NAME, STRING_OR_EMPTY(tp->clnt_sig_name)), SEND_ATTR_STR(TLS_ATTR_CLNT_SIG_CURVE, diff --git a/src/tls/tls_proxy_context_scan.c b/src/tls/tls_proxy_context_scan.c index 1d463ad..48aaff6 100644 --- a/src/tls/tls_proxy_context_scan.c +++ b/src/tls/tls_proxy_context_scan.c @@ -113,6 +113,8 @@ int tls_proxy_context_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, RECV_ATTR_STR(TLS_ATTR_KEX_NAME, kex_name), RECV_ATTR_STR(TLS_ATTR_KEX_CURVE, kex_curve), RECV_ATTR_INT(TLS_ATTR_KEX_BITS, &tls_context->kex_bits), + RECV_ATTR_INT(TLS_ATTR_CTOS_RPK, &tls_context->ctos_rpk), + RECV_ATTR_INT(TLS_ATTR_STOC_RPK, &tls_context->stoc_rpk), RECV_ATTR_STR(TLS_ATTR_CLNT_SIG_NAME, clnt_sig_name), RECV_ATTR_STR(TLS_ATTR_CLNT_SIG_CURVE, clnt_sig_curve), RECV_ATTR_INT(TLS_ATTR_CLNT_SIG_BITS, &tls_context->clnt_sig_bits), @@ -139,7 +141,7 @@ int tls_proxy_context_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, tls_context->srvr_sig_curve = vstring_export(srvr_sig_curve); tls_context->srvr_sig_dgst = vstring_export(srvr_sig_dgst); tls_context->namaddr = vstring_export(namaddr); - ret = (ret == 22 ? 1 : -1); + ret = (ret == 24 ? 1 : -1); if (ret != 1) { tls_proxy_context_free(tls_context); tls_context = 0; diff --git a/src/tls/tls_server.c b/src/tls/tls_server.c index 262cda9..88b3326 100644 --- a/src/tls/tls_server.c +++ b/src/tls/tls_server.c @@ -62,8 +62,8 @@ /* available as: /* .IP TLScontext->peer_status /* A bitmask field that records the status of the peer certificate -/* verification. One or more of TLS_CERT_FLAG_PRESENT and -/* TLS_CERT_FLAG_TRUSTED. +/* verification. One or more of TLS_CRED_FLAG_CERT, TLS_CRED_FLAG_RPK +/* and TLS_CERT_FLAG_TRUSTED. /* .IP TLScontext->peer_CN /* Extracted CommonName of the peer, or zero-length string /* when information could not be extracted. @@ -636,6 +636,13 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) return (0); } + /* + * Always support server->client raw public keys, if they're good enough + * for the client, they're good enough for us. + */ + tls_enable_server_rpk(server_ctx, NULL); + tls_enable_server_rpk(sni_ctx, NULL); + /* * Upref and share the cert store. Sadly we can't yet use * SSL_CTX_set1_cert_store(3) which was added in OpenSSL 1.1.0. @@ -865,11 +872,19 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) tls_free_context(TLScontext); return (0); } -#ifdef SSL_SECOP_PEER - /* When authenticating the peer, use 80-bit plus OpenSSL security level */ + + /* + * When encryption is mandatory use the 80-bit plus OpenSSL security level. + */ if (props->requirecert) SSL_set_security_level(TLScontext->con, 1); -#endif + + /* + * Also enable client->server raw public keys, provided we're not + * interested in client certificate fingerprints. + */ + if (props->enable_rpk) + tls_enable_client_rpk(NULL, TLScontext->con); /* * Before really starting anything, try to seed the PRNG a little bit @@ -946,6 +961,7 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) { const SSL_CIPHER *cipher; X509 *peer; + EVP_PKEY *pkey = 0; char buf[CCERT_BUFSIZ]; /* Turn off packet dump if only dumping the handshake */ @@ -966,8 +982,17 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) * actual information. We want to save it for later use. */ peer = TLS_PEEK_PEER_CERT(TLScontext->con); + if (peer) { + pkey = X509_get0_pubkey(peer); + } +#if OPENSSL_VERSION_PREREQ(3,2) + else { + pkey = SSL_get0_peer_rpk(TLScontext->con); + } +#endif + if (peer != NULL) { - TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT; + TLScontext->peer_status |= TLS_CRED_FLAG_CERT; if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED; @@ -981,16 +1006,23 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) } TLScontext->peer_CN = tls_peer_CN(peer, TLScontext); TLScontext->issuer_CN = tls_issuer_CN(peer, TLScontext); - TLScontext->peer_cert_fprint = tls_cert_fprint(peer, TLScontext->mdalg); - TLScontext->peer_pkey_fprint = tls_pkey_fprint(peer, TLScontext->mdalg); + TLScontext->peer_cert_fprint = + tls_cert_fprint(peer, TLScontext->mdalg); + TLScontext->peer_pkey_fprint = + tls_pkey_fprint(pkey, TLScontext->mdalg); if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) { - msg_info("%s: subject_CN=%s, issuer=%s, fingerprint=%s" - ", pkey_fingerprint=%s", + msg_info("%s: subject_CN=%s, issuer=%s%s%s%s%s", TLScontext->namaddr, TLScontext->peer_CN, TLScontext->issuer_CN, - TLScontext->peer_cert_fprint, - TLScontext->peer_pkey_fprint); + *TLScontext->peer_cert_fprint ? + ", cert fingerprint=" : "", + *TLScontext->peer_cert_fprint ? + TLScontext->peer_cert_fprint : "", + *TLScontext->peer_pkey_fprint ? + ", pkey fingerprint=" : "", + *TLScontext->peer_pkey_fprint ? + TLScontext->peer_pkey_fprint : ""); } TLS_FREE_PEER_CERT(peer); @@ -1013,7 +1045,22 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) TLScontext->peer_CN = mystrdup(""); TLScontext->issuer_CN = mystrdup(""); TLScontext->peer_cert_fprint = mystrdup(""); - TLScontext->peer_pkey_fprint = mystrdup(""); + if (!pkey) { + TLScontext->peer_pkey_fprint = mystrdup(""); + } else { + + /* + * Raw public keys don't involve CA trust, and we don't have a + * way to associate DANE TLSA RRs with clients just yet, we just + * make the fingerprint available to the access(5) layer. + */ + TLScontext->peer_status |= TLS_CRED_FLAG_RPK; + TLScontext->peer_pkey_fprint = + tls_pkey_fprint(pkey, TLScontext->mdalg); + if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) + msg_info("%s: raw public key fingerprint=%s", + TLScontext->namaddr, TLScontext->peer_pkey_fprint); + } } /* diff --git a/src/tls/tls_verify.c b/src/tls/tls_verify.c index f32f32b..c643f18 100644 --- a/src/tls/tls_verify.c +++ b/src/tls/tls_verify.c @@ -144,6 +144,7 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx) int depth; SSL *con; TLS_SESS_STATE *TLScontext; + EVP_PKEY *rpk = 0; /* May be NULL as of OpenSSL 1.0, thanks for the API change! */ cert = X509_STORE_CTX_get_current_cert(ctx); @@ -151,6 +152,10 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx) con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); TLScontext = SSL_get_ex_data(con, TLScontext_index); depth = X509_STORE_CTX_get_error_depth(ctx); +#if OPENSSL_VERSION_PREREQ(3,2) + if (cert == 0) + rpk = X509_STORE_CTX_get0_rpk(ctx); +#endif /* * Transient failures to load the (DNS or synthetic TLSA) trust settings @@ -174,12 +179,15 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx) update_error_state(TLScontext, depth, cert, err); if (TLScontext->log_mask & TLS_LOG_VERBOSE) { - if (cert) + if (cert) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); - else - strcpy(buf, ""); - msg_info("%s: depth=%d verify=%d subject=%s", - TLScontext->namaddr, depth, ok, printable(buf, '?')); + msg_info("%s: depth=%d verify=%d subject=%s", + TLScontext->namaddr, depth, ok, printable(buf, '?')); + } else if (rpk) { + msg_info("%s: verify=%d raw public key", TLScontext->namaddr, ok); + } else { + msg_info("%s: depth=%d verify=%d", TLScontext->namaddr, depth, ok); + } } return (1); } diff --git a/src/tlsproxy/tlsproxy.c b/src/tlsproxy/tlsproxy.c index 7c0d814..0ebf52c 100644 --- a/src/tlsproxy/tlsproxy.c +++ b/src/tlsproxy/tlsproxy.c @@ -237,6 +237,12 @@ /* .IP "\fBtlsproxy_tls_chain_files ($smtpd_tls_chain_files)\fR" /* Files with the Postfix \fBtlsproxy\fR(8) server keys and certificate /* chains in PEM format. +/* .PP +/* Available in Postfix version 3.9 and later: +/* .IP "\fBtlsproxy_tls_enable_rpk ($smtpd_tls_enable_rpk)\fR" +/* Request that remote SMTP clients send an RFC7250 raw public key +/* instead of an X.509 certificate, when asking or requiring client +/* authentication. /* STARTTLS CLIENT CONTROLS /* .ad /* .fi @@ -436,6 +442,7 @@ bool var_smtpd_use_tls; bool var_smtpd_enforce_tls; bool var_smtpd_tls_ask_ccert; bool var_smtpd_tls_req_ccert; +bool var_smtpd_tls_enable_rpk; bool var_smtpd_tls_set_sessid; char *var_smtpd_relay_ccerts; char *var_smtpd_tls_chain_files; @@ -465,6 +472,7 @@ bool var_tlsp_use_tls; bool var_tlsp_enforce_tls; bool var_tlsp_tls_ask_ccert; bool var_tlsp_tls_req_ccert; +bool var_tlsp_tls_enable_rpk; bool var_tlsp_tls_set_sessid; char *var_tlsp_tls_chain_files; char *var_tlsp_tls_cert_file; @@ -1081,6 +1089,7 @@ static int tlsp_server_start_pre_handshake(TLSP_STATE *state) timeout = 0, /* unused */ requirecert = (var_tlsp_tls_req_ccert && var_tlsp_enforce_tls), + enable_rpk = var_tlsp_tls_enable_rpk, serverid = state->server_id, namaddr = state->remote_endpt, cipher_grade = cipher_grade, @@ -1827,6 +1836,7 @@ int main(int argc, char **argv) VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls, VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert, VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert, + VAR_SMTPD_TLS_ENABLE_RPK, DEF_SMTPD_TLS_ENABLE_RPK, &var_smtpd_tls_enable_rpk, VAR_SMTPD_TLS_SET_SESSID, DEF_SMTPD_TLS_SET_SESSID, &var_smtpd_tls_set_sessid, VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls, VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_tls, @@ -1837,6 +1847,7 @@ int main(int argc, char **argv) VAR_TLSP_ENFORCE_TLS, DEF_TLSP_ENFORCE_TLS, &var_tlsp_enforce_tls, VAR_TLSP_TLS_ACERT, DEF_TLSP_TLS_ACERT, &var_tlsp_tls_ask_ccert, VAR_TLSP_TLS_RCERT, DEF_TLSP_TLS_RCERT, &var_tlsp_tls_req_ccert, + VAR_TLSP_TLS_ENABLE_RPK, DEF_TLSP_TLS_ENABLE_RPK, &var_tlsp_tls_enable_rpk, VAR_TLSP_TLS_SET_SESSID, DEF_TLSP_TLS_SET_SESSID, &var_tlsp_tls_set_sessid, VAR_TLSP_CLNT_USE_TLS, DEF_TLSP_CLNT_USE_TLS, &var_tlsp_clnt_use_tls, VAR_TLSP_CLNT_ENFORCE_TLS, DEF_TLSP_CLNT_ENFORCE_TLS, &var_tlsp_clnt_enforce_tls, diff --git a/src/trivial-rewrite/resolve.c b/src/trivial-rewrite/resolve.c index 40e6aa5..df761e7 100644 --- a/src/trivial-rewrite/resolve.c +++ b/src/trivial-rewrite/resolve.c @@ -427,7 +427,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, if (!valid_mailhost_literal(rcpt_domain, DONT_GRIPE)) *flags |= RESOLVE_FLAG_ERROR; } else if (var_smtputf8_enable - && valid_utf8_string(STR(nextrcpt), LEN(nextrcpt)) == 0) { + && valid_utf8_stringz(STR(nextrcpt)) == 0) { *flags |= RESOLVE_FLAG_ERROR; } else if (!valid_utf8_hostname(var_smtputf8_enable, rcpt_domain, DONT_GRIPE)) { diff --git a/src/trivial-rewrite/trivial-rewrite.c b/src/trivial-rewrite/trivial-rewrite.c index 675af80..bb8da09 100644 --- a/src/trivial-rewrite/trivial-rewrite.c +++ b/src/trivial-rewrite/trivial-rewrite.c @@ -122,9 +122,10 @@ /* .PP /* Available in Postfix 2.2 and later: /* .IP "\fBremote_header_rewrite_domain (empty)\fR" -/* Don't rewrite message headers from remote clients at all when -/* this parameter is empty; otherwise, rewrite message headers and -/* append the specified domain name to incomplete addresses. +/* Rewrite or add message headers in mail from remote clients if +/* the remote_header_rewrite_domain parameter value is non-empty, +/* updating incomplete addresses with the domain specified in the +/* remote_header_rewrite_domain parameter, and adding missing headers. /* ROUTING CONTROLS /* .ad /* .fi @@ -141,10 +142,12 @@ /* final delivery to domains listed with $virtual_mailbox_domains. /* .IP "\fBrelay_transport (relay)\fR" /* The default mail delivery transport and next-hop destination for -/* remote delivery to domains listed with $relay_domains. +/* the relay domain address class: recipient domains that match +/* $relay_domains. /* .IP "\fBdefault_transport (smtp)\fR" /* The default mail delivery transport and next-hop destination for -/* destinations that do not match $mydestination, $inet_interfaces, +/* the default domain class: recipient domains that do not match +/* $mydestination, $inet_interfaces, /* $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, /* or $relay_domains. /* .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR" @@ -152,8 +155,8 @@ /* matches subdomains of example.com, /* instead of requiring an explicit ".example.com" pattern. /* .IP "\fBrelayhost (empty)\fR" -/* The next-hop destination(s) for non-local mail; overrides non-local -/* domains in recipient addresses. +/* The next-hop destination(s) for non-local mail; takes precedence +/* over non-local domains in recipient addresses. /* .IP "\fBtransport_maps (empty)\fR" /* Optional lookup tables with mappings from recipient address to /* (message delivery transport, next-hop destination). diff --git a/src/util/Makefile.in b/src/util/Makefile.in index f69dec5..01211fb 100644 --- a/src/util/Makefile.in +++ b/src/util/Makefile.in @@ -45,7 +45,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ byte_mask.c known_tcp_ports.c argv_split_at.c dict_stream.c \ sane_strtol.c hash_fnv.c ldseed.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c \ mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c inet_prefix_top.c \ - inet_addr_sizes.c + inet_addr_sizes.c quote_for_json.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ @@ -91,7 +91,8 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o \ byte_mask.o known_tcp_ports.o argv_split_at.o dict_stream.o \ sane_strtol.o hash_fnv.o ldseed.o mkmap_db.o mkmap_dbm.o \ - mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o + mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o \ + quote_for_json.o # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. @@ -145,7 +146,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \ vbuf_print split_qnameval vstream msg_logger byte_mask \ known_tcp_ports dict_stream find_inet binhash hash_fnv argv \ - clean_env inet_prefix_top + clean_env inet_prefix_top printable readlline quote_for_json PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) $(LIB_PREFIX)lmdb$(LIB_SUFFIX) \ $(LIB_PREFIX)cdb$(LIB_SUFFIX) $(LIB_PREFIX)sdbm$(LIB_SUFFIX) HTABLE_FIX = NORANDOMIZE=1 @@ -365,6 +366,16 @@ unescape: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +printable: $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + +readlline: $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + hex_quote: $(LIB) mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) @@ -609,6 +620,11 @@ inet_prefix_top: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +quote_for_json: $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + tests: all valid_hostname_test mac_expand_test dict_test unescape_test \ hex_quote_test ctable_test inet_addr_list_test base64_code_test \ attr_scan64_test attr_scan0_test host_port_test dict_tests \ @@ -618,7 +634,8 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \ strcasecmp_utf8_test vbuf_print_test miss_endif_cidr_test \ miss_endif_regexp_test split_qnameval_test vstring_test \ vstream_test byte_mask_tests mystrtok_test known_tcp_ports_test \ - binhash_test argv_test inet_prefix_top_test + binhash_test argv_test inet_prefix_top_test printable_test \ + valid_utf8_string_test readlline_test quote_for_json_test dict_tests: all dict_test \ dict_pcre_tests dict_cidr_test dict_thash_test dict_static_test \ @@ -650,6 +667,15 @@ unescape_test: unescape unescape.in unescape.ref # diff unescape.in unescape.tmp rm -f unescape.tmp +printable_test: printable + $(SHLIB_ENV) ${VALGRIND} ./printable + +readlline_test: readlline + $(SHLIB_ENV) ${VALGRIND} ./readlline + +valid_utf8_string_test: valid_utf8_string + $(SHLIB_ENV) ${VALGRIND} ./valid_utf8_string + hex_quote_test: hex_quote $(SHLIB_ENV) ${VALGRIND} ./hex_quote hex_quote.tmp od -cb hex_quote.ref @@ -1083,6 +1109,9 @@ argv_test: argv inet_prefix_top_test: inet_prefix_top $(SHLIB_ENV) ${VALGRIND} ./inet_prefix_top +quote_for_json_test: quote_for_json + $(SHLIB_ENV) ${VALGRIND} ./quote_for_json + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ @@ -1119,9 +1148,12 @@ allspace.o: vbuf.h allspace.o: vstring.h argv.o: argv.c argv.o: argv.h +argv.o: check_arg.h argv.o: msg.h argv.o: mymalloc.h argv.o: sys_defs.h +argv.o: vbuf.h +argv.o: vstring.h argv_attr_print.o: argv.h argv_attr_print.o: argv_attr.h argv_attr_print.o: argv_attr_print.c @@ -2157,6 +2189,7 @@ logwriter.o: logwriter.c logwriter.o: logwriter.h logwriter.o: msg.h logwriter.o: mymalloc.h +logwriter.o: name_code.h logwriter.o: safe_open.h logwriter.o: sys_defs.h logwriter.o: vbuf.h @@ -2525,11 +2558,16 @@ posix_signals.o: posix_signals.c posix_signals.o: posix_signals.h posix_signals.o: sys_defs.h printable.o: check_arg.h +printable.o: parse_utf8_char.h printable.o: printable.c printable.o: stringops.h printable.o: sys_defs.h printable.o: vbuf.h printable.o: vstring.h +quote_for_json.o: quote_for_json.c +quote_for_json.o: stringops.h +quote_for_json.o: sys_defs.h +quote_for_json.o: vstring.h rand_sleep.o: iostuff.h rand_sleep.o: msg.h rand_sleep.o: myrand.h @@ -2848,6 +2886,7 @@ valid_utf8_hostname.o: valid_utf8_hostname.h valid_utf8_hostname.o: vbuf.h valid_utf8_hostname.o: vstring.h valid_utf8_string.o: check_arg.h +valid_utf8_string.o: parse_utf8_char.h valid_utf8_string.o: stringops.h valid_utf8_string.o: sys_defs.h valid_utf8_string.o: valid_utf8_string.c diff --git a/src/util/argv.c b/src/util/argv.c index 4e05fd0..332426e 100644 --- a/src/util/argv.c +++ b/src/util/argv.c @@ -53,6 +53,11 @@ /* ssize_t pos; /* ssize_t how_many; /* +/* char *argv_join(buf, argvp, delim) +/* VSTRING *buf; +/* ARGV *argvp; +/* int delim; +/* /* void ARGV_FAKE_BEGIN(argv, arg) /* const char *arg; /* @@ -109,6 +114,10 @@ /* starting at the specified array position. The result is /* null-terminated. /* +/* argv_join() joins all elements in an array using the +/* specified delimiter value, and appends the result to the +/* specified buffer. +/* /* ARGV_FAKE_BEGIN/END are an optimization for the case where /* a single string needs to be passed into an ARGV-based /* interface. ARGV_FAKE_BEGIN() opens a statement block and @@ -148,6 +157,7 @@ #include "mymalloc.h" #include "msg.h" +#include "vstring.h" #include "argv.h" #ifdef TEST @@ -379,6 +389,20 @@ void argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many) argvp->argc -= how_many; } +/* argv_join - concatenate array elements with delimiter */ + +char *argv_join(VSTRING *buf, ARGV *argv, int delim) +{ + char **cpp; + + for (cpp = argv->argv; *cpp; cpp++) { + vstring_strcat(buf, *cpp); + if (cpp[1]) + VSTRING_ADDCH(buf, delim); + } + return (vstring_str(buf)); +} + #ifdef TEST /* @@ -402,6 +426,7 @@ typedef struct TEST_CASE { const char *exp_panic_msg; /* expected panic */ int exp_argc; /* expected array length */ const char *exp_argv[ARRAY_LEN]; /* expected array content */ + int join_delim; /* argv_join() delimiter */ } TEST_CASE; #define TERMINATE_ARRAY (1) @@ -559,6 +584,24 @@ static ARGV *test_argv_bad_delete3(const TEST_CASE *tp, ARGV *argvp) return (argvp); } +/* test_argv_join - populate, join, and overwrite */ + +static ARGV *test_argv_join(const TEST_CASE *tp, ARGV *argvp) +{ + VSTRING *buf = vstring_alloc(100); + + /* + * Impedance mismatch: argv_join() produces output to VSTRING, but the + * test fixture wants output to ARGV. + */ + test_argv_populate(tp, argvp); + argv_join(buf, argvp, tp->join_delim); + argv_delete(argvp, 0, argvp->argc); + argv_add(argvp, vstring_str(buf), ARGV_END); + vstring_free(buf); + return (argvp); +} + /* test_argv_verify - verify result */ static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp) @@ -573,7 +616,7 @@ static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp) } if (strcmp(vstring_str(test_panic_str), tp->exp_panic_msg) != 0) { msg_warn("test case '%s': got '%s', want: '%s'", - tp->label, vstring_str(test_panic_str), tp->exp_panic_msg); + tp->label, vstring_str(test_panic_str), tp->exp_panic_msg); return (FAIL); } return (PASS); @@ -682,6 +725,18 @@ static const TEST_CASE test_cases[] = { {"foo", "baz", "bar", 0}, 0, test_argv_bad_delete3, "argv_delete bad range: (start=100 count=1)" }, + {"argv_join, multiple strings", + {"foo", "baz", "bar", 0}, 0, test_argv_join, + 0, 1, {"foo:baz:bar", 0}, ':' + }, + {"argv_join, one string", + {"foo", 0}, 0, test_argv_join, + 0, 1, {"foo", 0}, ':' + }, + {"argv_join, empty", + {0}, 0, test_argv_join, + 0, 1, {"", 0}, ':' + }, 0, }; diff --git a/src/util/argv.h b/src/util/argv.h index b0098ce..f1e746a 100644 --- a/src/util/argv.h +++ b/src/util/argv.h @@ -33,6 +33,8 @@ extern void argv_truncate(ARGV *, ssize_t); extern void argv_insert_one(ARGV *, ssize_t, const char *); extern void argv_replace_one(ARGV *, ssize_t, const char *); extern void argv_delete(ARGV *, ssize_t, ssize_t); +struct VSTRING; +extern char *argv_join(struct VSTRING *buf, ARGV *, int); extern ARGV *argv_free(ARGV *); extern ARGV *argv_split(const char *, const char *); diff --git a/src/util/casefold.c b/src/util/casefold.c index d3ebd4b..94860b8 100644 --- a/src/util/casefold.c +++ b/src/util/casefold.c @@ -300,7 +300,7 @@ int main(int argc, char **argv) encode_utf8(buffer, codepoint); if (msg_verbose) vstream_printf("U+%X -> %s\n", codepoint, STR(buffer)); - if (valid_utf8_string(STR(buffer), LEN(buffer)) == 0) + if (valid_utf8_stringz(STR(buffer)) == 0) msg_fatal("bad utf-8 encoding for U+%X\n", codepoint); casefold(dest, STR(buffer)); } diff --git a/src/util/dict_inline.c b/src/util/dict_inline.c index 72339b2..d7f9344 100644 --- a/src/util/dict_inline.c +++ b/src/util/dict_inline.c @@ -87,7 +87,7 @@ DICT *dict_inline_open(const char *name, int open_flags, int dict_flags) */ if (DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags) && allascii(name) == 0 - && valid_utf8_string(name, strlen(name)) == 0) + && valid_utf8_stringz(name) == 0) DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name, open_flags, dict_flags, "bad UTF-8 syntax: \"%s:%s\"; " diff --git a/src/util/dict_thash.c b/src/util/dict_thash.c index 69eb17b..bae4a63 100644 --- a/src/util/dict_thash.c +++ b/src/util/dict_thash.c @@ -127,7 +127,7 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) */ if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) && allascii(STR(line_buffer)) == 0 - && valid_utf8_string(STR(line_buffer), LEN(line_buffer)) == 0) { + && valid_utf8_stringz(STR(line_buffer)) == 0) { msg_warn("%s, line %d: non-UTF-8 input \"%s\"" " -- ignoring this line", VSTREAM_PATH(fp), lineno, STR(line_buffer)); @@ -181,8 +181,8 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags) " is this an alias file?", path, lineno); /* - * Optionally treat the value as a filename, and replace the value - * with the BASE64-encoded content of the named file. + * Optionally treat the value as a filename, and replace the + * value with the BASE64-encoded content of the named file. */ if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) { VSTRING *base64_buf; diff --git a/src/util/dict_utf8.c b/src/util/dict_utf8.c index f1fc65a..9bb6b7b 100644 --- a/src/util/dict_utf8.c +++ b/src/util/dict_utf8.c @@ -100,7 +100,7 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string, /* * Validate UTF-8 without casefolding. */ - if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) { + if (!allascii(string) && valid_utf8_stringz(string) == 0) { if (err) *err = "malformed UTF-8 or invalid codepoint"; return (0); @@ -123,7 +123,7 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string, static int dict_utf8_check(const char *string, CONST_CHAR_STAR *err) { - if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) { + if (!allascii(string) && valid_utf8_stringz(string) == 0) { if (err) *err = "malformed UTF-8 or invalid codepoint"; return (0); diff --git a/src/util/inet_prefix_top.c b/src/util/inet_prefix_top.c index 8d5af00..f35d5f0 100644 --- a/src/util/inet_prefix_top.c +++ b/src/util/inet_prefix_top.c @@ -164,6 +164,7 @@ int main(int argc, char **argv) msg_info("PASS %s/%d", str_name_code(af_map, tp->in_af), tp->in_prefix_len); } + myfree(act_prefix); } msg_info("PASS=%d FAIL=%d", pass, fail); return (fail > 0); diff --git a/src/util/logwriter.c b/src/util/logwriter.c index aea2767..4a18be3 100644 --- a/src/util/logwriter.c +++ b/src/util/logwriter.c @@ -21,6 +21,9 @@ /* const char *path, /* const char *buffer, /* ssize_t buflen) +/* +/* int set_logwriter_create_perms( +/* const char *mode) /* DESCRIPTION /* This module manages a logfile writer. /* @@ -38,6 +41,15 @@ /* logwriter_one_shot() combines all the above operations. The /* result is zero if successful, VSTREAM_EOF if any operation /* failed. +/* +/* set_logwriter_create_perms() sets the file permissions that +/* will be used when creating a logfile. Valid inputs are +/* "644", "640", and "600". Leading zeros are allowed and +/* ignored. +/* DIAGNOSTICS +/* Fatal error: logfile create error; warning: logfile permission +/* change error. set_logwriter_create_perms() returns the file +/* create permission if the request is valid, -1 otherwise. /* LICENSE /* .ad /* .fi @@ -66,10 +78,12 @@ #include #include #include +#include /* * Application-specific. */ +static int logwriter_perms = 0600; /* logwriter_open_or_die - open logfile */ @@ -82,7 +96,7 @@ VSTREAM *logwriter_open_or_die(const char *path) #define NO_CHOWN (-1) #define NO_CHGRP (-1) - fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, 0644, + fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, logwriter_perms, NO_STATP, NO_CHOWN, NO_CHGRP, why); if (fp == 0) msg_fatal("open logfile '%s': %s", path, vstring_str(why)); @@ -122,3 +136,21 @@ int logwriter_one_shot(const char *path, const char *buf, ssize_t len) err |= logwriter_close(fp); return (err ? VSTREAM_EOF : 0); } + +/* set_logwriter_create_perms - logfile permission control */ + +int set_logwriter_create_perms(const char *mode_str) +{ + static const NAME_CODE sane_perms[] = { + "644", 0644, + "640", 0640, + "600", 0600, + 0, -1, + }; + int perms; + + if ((perms = name_code(sane_perms, NAME_CODE_FLAG_NONE, + mode_str + strspn(mode_str, "0"))) != -1) + logwriter_perms = perms; + return (perms); +} diff --git a/src/util/logwriter.h b/src/util/logwriter.h index f5266e4..c827d25 100644 --- a/src/util/logwriter.h +++ b/src/util/logwriter.h @@ -23,6 +23,7 @@ extern VSTREAM *logwriter_open_or_die(const char *); extern int logwriter_write(VSTREAM *, const char *, ssize_t); extern int logwriter_close(VSTREAM *); extern int logwriter_one_shot(const char *, const char *, ssize_t); +extern int set_logwriter_create_perms(const char *); /* LICENSE /* .ad diff --git a/src/util/midna_domain.c b/src/util/midna_domain.c index 333a5c9..bc016b6 100644 --- a/src/util/midna_domain.c +++ b/src/util/midna_domain.c @@ -178,7 +178,7 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context /* * Paranoia: do not expose uidna_*() to unfiltered network data. */ - if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) { + if (allascii(name) == 0 && valid_utf8_stringz(name) == 0) { msg_warn("%s: Problem translating domain \"%.100s\" to ASCII form: %s", myname, name, "malformed UTF-8"); return (0); @@ -232,7 +232,7 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context) /* * Paranoia: do not expose uidna_*() to unfiltered network data. */ - if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) { + if (allascii(name) == 0 && valid_utf8_stringz(name) == 0) { msg_warn("%s: Problem translating domain \"%.100s\" to UTF-8 form: %s", myname, name, "malformed UTF-8"); return (0); diff --git a/src/util/parse_utf8_char.h b/src/util/parse_utf8_char.h new file mode 100644 index 0000000..b00a1c2 --- /dev/null +++ b/src/util/parse_utf8_char.h @@ -0,0 +1,122 @@ +/*++ +/* NAME +/* parse_utf8_char 3h +/* SUMMARY +/* parse one UTF-8 multibyte character +/* SYNOPSIS +/* #include +/* +/* char *parse_utf8_char(str, end) +/* const char *str; +/* const char *end; +/* DESCRIPTION +/* parse_utf8_char() determines if the byte sequence starting +/* at \fBstr\fR begins with a complete UTF-8 character as +/* defined in RFC 3629. That is, a proper encoding of code +/* points U+0000..U+10FFFF, excluding over-long encodings and +/* excluding U+D800..U+DFFF surrogates. +/* +/* When the byte sequence starting at \fBstr\fR begins with a +/* complete UTF-8 character, this function returns a pointer +/* to the last byte in that character. Otherwise, it returns +/* a null pointer. +/* +/* The \fBend\fR argument is either null (the byte sequence +/* starting at \fBstr\fR must be null terminated), or \fBend +/* - str\fR specifies the length of the byte sequence. +/* BUGS +/* Code points in the range U+FDD0..U+FDEF and ending in FFFE +/* or FFFF are non-characters in UNICODE. This function does +/* not reject these. +/* 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 +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA +/*--*/ + + /* + * System library. + */ +#include + +#ifdef NO_INLINE +#define inline /* */ +#endif + +/* parse_utf8_char - parse and validate one UTF8 multibyte sequence */ + +static inline char *parse_utf8_char(const char *str, const char *end) +{ + const unsigned char *cp = (const unsigned char *) str; + const unsigned char *ep = (const unsigned char *) end; + unsigned char c0, ch; + + /* + * Optimized for correct input, time, space, and for CPUs that have a + * decent number of registers. Other implementation considerations: + * + * - In the UTF-8 encoding, a non-leading byte is never null. Therefore, + * this function will correctly reject a partial UTF-8 character at the + * end of a null-terminated string. + * + * - If the "end" argument is a null constant, and if this function is + * inlined, then an optimizing compiler should propagate the constant + * through the "ep" variable, and eliminate any code branches that + * require ep != 0. + */ + /* Single-byte encodings. */ + if (EXPECTED((c0 = *cp) <= 0x7f) /* we know that c0 >= 0x0 */ ) { + return ((char *) cp); + } + /* Two-byte encodings. */ + else if (EXPECTED(c0 <= 0xdf) /* we know that c0 >= 0x80 */ ) { + /* Exclude over-long encodings. */ + if (UNEXPECTED(c0 < 0xc2) + || UNEXPECTED(ep && cp + 1 >= ep) + /* Require UTF-8 tail byte. */ + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) + return (0); + return ((char *) cp); + } + /* Three-byte encodings. */ + else if (EXPECTED(c0 <= 0xef) /* we know that c0 >= 0xe0 */ ) { + if (UNEXPECTED(ep && cp + 2 >= ep) + /* Exclude over-long encodings. */ + || UNEXPECTED((ch = *++cp) < (c0 == 0xe0 ? 0xa0 : 0x80)) + /* Exclude U+D800..U+DFFF. */ + || UNEXPECTED(ch > (c0 == 0xed ? 0x9f : 0xbf)) + /* Require UTF-8 tail byte. */ + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) + return (0); + return ((char *) cp); + } + /* Four-byte encodings. */ + else if (EXPECTED(c0 <= 0xf4) /* we know that c0 >= 0xf0 */ ) { + if (UNEXPECTED(ep && cp + 3 >= ep) + /* Exclude over-long encodings. */ + || UNEXPECTED((ch = *++cp) < (c0 == 0xf0 ? 0x90 : 0x80)) + /* Exclude code points above U+10FFFF. */ + || UNEXPECTED(ch > (c0 == 0xf4 ? 0x8f : 0xbf)) + /* Require UTF-8 tail byte. */ + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80) + /* Require UTF-8 tail byte. */ + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) + return (0); + return ((char *) cp); + } + /* Invalid: c0 >= 0xf5 */ + else { + return (0); + } +} + +#undef inline diff --git a/src/util/printable.c b/src/util/printable.c index 6c148fd..0e1ae19 100644 --- a/src/util/printable.c +++ b/src/util/printable.c @@ -45,6 +45,10 @@ /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA /*--*/ /* System library. */ @@ -56,8 +60,9 @@ /* Utility library. */ #include "stringops.h" +#include "parse_utf8_char.h" -int util_utf8_enable = 0; +int util_utf8_enable = 0; /* printable - binary compatibility */ @@ -74,27 +79,150 @@ char *printable(char *string, int replacement) char *printable_except(char *string, int replacement, const char *except) { - unsigned char *cp; + char *cp; + char *last; int ch; /* - * XXX Replace invalid UTF8 sequences (too short, over-long encodings, - * out-of-range code points, etc). See valid_utf8_string.c. + * In case of a non-UTF8 sequence (bad leader byte, bad non-leader byte, + * over-long encodings, out-of-range code points, etc), replace the first + * byte, and try to resynchronize at the next byte. */ - cp = (unsigned char *) string; - while ((ch = *cp) != 0) { - if (ISASCII(ch) && (ISPRINT(ch) || (except && strchr(except, ch)))) { - /* ok */ - } else if (util_utf8_enable && ch >= 194 && ch <= 254 - && cp[1] >= 128 && cp[1] < 192) { - /* UTF8; skip the rest of the bytes in the character. */ - while (cp[1] >= 128 && cp[1] < 192) - cp++; - } else { - /* Not ASCII and not UTF8. */ - *cp = replacement; +#define PRINT_OR_EXCEPT(ch) (ISPRINT(ch) || (except && strchr(except, ch))) + + for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++) { + if (util_utf8_enable == 0) { + if (ISASCII(ch) && PRINT_OR_EXCEPT(ch)) + continue; + } else if ((last = parse_utf8_char(cp, 0)) == cp) { /* ASCII */ + if (PRINT_OR_EXCEPT(ch)) + continue; + } else if (last != 0) { /* Other UTF8 */ + cp = last; + continue; } - cp++; + *cp = replacement; } return (string); } + +#ifdef TEST + +#include +#include +#include +#include +#include +#include + + /* + * Test cases for 1-, 2-, and 3-byte encodings. Originally contributed by + * Viktor Dukhovni, and annotated using translate.google.com. + * + * See valid_utf8_string.c for single-error tests. + * + * XXX Need a test for 4-byte encodings, preferably with strings that can be + * displayed. + */ +struct testcase { + const char *name; + const char *input; + const char *expected;; +}; +static const struct testcase testcases[] = { + {"Printable ASCII", + "printable", "printable" + }, + {"ASCII with control character", + "non\bn-printable", "non?n-printable" + }, + {"Latin accented text, no error", + "na\303\257ve", "na\303\257ve" + }, + {"Latin text, with error", + "na\303ve", "na?ve" + }, + {"Viktor, Cyrillic, no error", + "\320\262\320\270\320\272\321\202\320\276\321\200", + "\320\262\320\270\320\272\321\202\320\276\321\200" + }, + {"Viktor, Cyrillic, two errors", + "\320\262\320\320\272\272\321\202\320\276\321\200", + "\320\262?\320\272?\321\202\320\276\321\200" + }, + {"Viktor, Hebrew, no error", + "\327\225\327\231\327\247\327\230\327\225\326\274\327\250", + "\327\225\327\231\327\247\327\230\327\225\326\274\327\250" + }, + {"Viktor, Hebrew, with error", + "\327\225\231\327\247\327\230\327\225\326\274\327\250", + "\327\225?\327\247\327\230\327\225\326\274\327\250" + }, + {"Chinese (Simplified), no error", + "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345\221\212", + "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345\221\212" + }, + {"Chinese (Simplified), with errors", + "\344\270\255\345\344\272\222\350\224\347\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345", + "\344\270\255?\344\272\222??\347\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245?" + }, +}; + +int main(int argc, char **argv) +{ + const struct testcase *tp; + int pass; + int fail; + +#define NUM_TESTS sizeof(testcases)/sizeof(testcases[0]) + + msg_vstream_init(basename(argv[0]), VSTREAM_ERR); + util_utf8_enable = 1; + + for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) { + char *input; + char *actual; + int ok = 0; + + /* + * Notes: + * + * - The input is modified, therefore it must be copied. + * + * - The msg(3) functions use printable() which interferes when logging + * inputs and outputs. Use vstream_fprintf() instead. + */ + vstream_fprintf(VSTREAM_ERR, "RUN %s\n", tp->name); + input = mystrdup(tp->input); + actual = printable(input, '?'); + + if (strcmp(actual, tp->expected) != 0) { + vstream_fprintf(VSTREAM_ERR, "input: >%s<, got: >%s<, want: >%s<\n", + tp->input, actual, tp->expected); + } else { + vstream_fprintf(VSTREAM_ERR, "input: >%s<, got and want: >%s<\n", + tp->input, actual); + ok = 1; + } + if (ok) { + vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name); + pass++; + } else { + vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name); + fail++; + } + myfree(input); + } + msg_info("PASS=%d FAIL=%d", pass, fail); + return (fail > 0); +} + +#endif diff --git a/src/util/quote_for_json.c b/src/util/quote_for_json.c new file mode 100644 index 0000000..f54af3f --- /dev/null +++ b/src/util/quote_for_json.c @@ -0,0 +1,218 @@ +/*++ +/* NAME +/* quote_for_json 3 +/* SUMMARY +/* quote UTF-8 string value for JSON +/* SYNOPSIS +/* #include +/* +/* char *quote_for_json( +/* VSTRING *result, +/* const char *in, +/* ssize_t len) +/* +/* char *quote_for_json_append( +/* VSTRING *result, +/* const char *in, +/* ssize_t len) +/* DESCRIPTION +/* quote_for_json() takes well-formed UTF-8 encoded text, +/* quotes that text compliant with RFC 4627, and returns a +/* pointer to the resulting text. The input may contain null +/* bytes, but the output will not. +/* +/* quote_for_json() produces short (two-letter) escape sequences +/* for common control characters, double quote and backslash. +/* It will not quote "/" (0x2F), and will quote DEL (0x7f) as +/* \u007F to make it printable. The input byte sequence "\uXXXX" +/* is quoted like any other text (the "\" is escaped as "\\"). +/* +/* quote_for_json() does not perform UTF-8 validation. The caller +/* should use valid_utf8_string() or printable() as appropriate. +/* +/* quote_for_json_append() appends the output to the result buffer. +/* +/* Arguments: +/* .IP result +/* Storage for the result, resized automatically. +/* .IP in +/* Pointer to the input byte sequence. +/* .IP len +/* The length of the input byte sequence, or a negative number +/* when the byte sequence is null-terminated. +/* DIAGNOSTICS +/* Fatal error: memory allocation error. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/* +/* Wietse Venema +/* porcupine.org +/*--*/ + + /* + * System library. + */ +#include +#include +#include + + /* + * Utility library. + */ +#include +#include + +#define STR(x) vstring_str(x) + +/* quote_for_json_append - quote JSON string, append result */ + +char *quote_for_json_append(VSTRING *result, const char *text, ssize_t len) +{ + const char *cp; + int ch; + + if (len < 0) + len = strlen(text); + + for (cp = text; len > 0; len--, cp++) { + ch = *(const unsigned char *) cp; + if (UNEXPECTED(ISCNTRL(ch))) { + switch (ch) { + case '\b': + VSTRING_ADDCH(result, '\\'); + VSTRING_ADDCH(result, 'b'); + break; + case '\f': + VSTRING_ADDCH(result, '\\'); + VSTRING_ADDCH(result, 'f'); + break; + case '\n': + VSTRING_ADDCH(result, '\\'); + VSTRING_ADDCH(result, 'n'); + break; + case '\r': + VSTRING_ADDCH(result, '\\'); + VSTRING_ADDCH(result, 'r'); + break; + case '\t': + VSTRING_ADDCH(result, '\\'); + VSTRING_ADDCH(result, 't'); + break; + default: + /* All other controls including DEL and NUL. */ + vstring_sprintf_append(result, "\\u%04X", ch); + break; + } + } else { + switch (ch) { + case '\\': + case '"': + VSTRING_ADDCH(result, '\\'); + /* FALLTHROUGH */ + default: + /* Includes malformed UTF-8. */ + VSTRING_ADDCH(result, ch); + break; + } + } + } + VSTRING_TERMINATE(result); + return (STR(result)); +} + +/* quote_for_json - quote JSON string */ + +char *quote_for_json(VSTRING *result, const char *text, ssize_t len) +{ + VSTRING_RESET(result); + return (quote_for_json_append(result, text, len)); +} + +#ifdef TEST + + /* + * System library. + */ +#include + + /* + * Utility library. + */ +#include +#include + +typedef struct TEST_CASE { + const char *label; /* identifies test case */ + char *(*fn) (VSTRING *, const char *, ssize_t); + const char *input; /* input string */ + ssize_t input_len; /* -1 or input length */ + const char *exp_res; /* expected result */ +} TEST_CASE; + +#define PASS (0) +#define FAIL (1) + + /* + * The test cases. + */ +static const TEST_CASE test_cases[] = { + {"ordinary ASCII text", quote_for_json, + " abcABC012.,[]{}/", -1, " abcABC012.,[]{}/", + }, + {"quote_for_json_append", quote_for_json_append, + "foo", -1, " abcABC012.,[]{}/foo", + }, + {"common control characters", quote_for_json, + "\b\f\r\n\t", -1, "\\b\\f\\r\\n\\t", + }, + {"uncommon control characters and DEL", quote_for_json, + "\0\01\037\040\176\177", 6, "\\u0000\\u0001\\u001F ~\\u007F", + }, + {"malformed UTF-8", quote_for_json, + "\\*\\uasd\\u007F\x80", -1, "\\\\*\\\\uasd\\\\u007F\x80", + }, + 0, +}; + +int main(int argc, char **argv) +{ + const TEST_CASE *tp; + int pass = 0; + int fail = 0; + VSTRING *res_buf = vstring_alloc(100); + + msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR); + + for (tp = test_cases; tp->label != 0; tp++) { + int test_fail = 0; + char *res; + + msg_info("RUN %s", tp->label); + res = tp->fn(res_buf, tp->input, tp->input_len); + if (strcmp(res, tp->exp_res) != 0) { + msg_warn("test case '%s': got '%s', want '%s'", + tp->label, res, tp->exp_res); + test_fail = 1; + } + if (test_fail) { + fail++; + msg_info("FAIL %s", tp->label); + test_fail = 1; + } else { + msg_info("PASS %s", tp->label); + pass++; + } + } + msg_info("PASS=%d FAIL=%d", pass, fail); + vstring_free(res_buf); + exit(fail != 0); +} + +#endif diff --git a/src/util/readlline.c b/src/util/readlline.c index 015877a..721b75f 100644 --- a/src/util/readlline.c +++ b/src/util/readlline.c @@ -85,9 +85,15 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line) int next; ssize_t start; char *cp; + int my_lineno = 0, my_first_line, got_null = 0; VSTRING_RESET(buf); + if (lineno == 0) + lineno = &my_lineno; + if (first_line == 0) + first_line = &my_first_line; + /* * Ignore comment lines, all whitespace lines, and empty lines. Terminate * at EOF or at the beginning of the next logical line. @@ -95,16 +101,19 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line) for (;;) { /* Read one line, possibly not newline terminated. */ start = LEN(buf); - while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n') + while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n') { VSTRING_ADDCH(buf, ch); - if (lineno != 0 && (ch == '\n' || LEN(buf) > start)) + if (ch == 0) + got_null = 1; + } + if (ch == '\n' || LEN(buf) > start) *lineno += 1; /* Ignore comment line, all whitespace line, or empty line. */ for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++) /* void */ ; if (cp == END(buf) || *cp == '#') vstring_truncate(buf, start); - else if (start == 0 && lineno != 0 && first_line != 0) + if (start == 0) *first_line = *lineno; /* Terminate at EOF or at the beginning of the next logical line. */ if (ch == VSTREAM_EOF) @@ -118,6 +127,20 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line) } VSTRING_TERMINATE(buf); + /* + * This code does not care about embedded null bytes, but callers do. + */ + if (got_null) { + const char *why = "text after null byte may be ignored"; + + if (*first_line == *lineno) + msg_warn("%s, line %d: %s", + VSTREAM_PATH(fp), *lineno, why); + else + msg_warn("%s, line %d-%d: %s", + VSTREAM_PATH(fp), *first_line, *lineno, why); + } + /* * Invalid input: continuing text without preceding text. Allowing this * would complicate "postconf -e", which implements its own multi-line @@ -136,3 +159,205 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line) */ return (LEN(buf) > 0 ? buf : 0); } + + /* + * Stand-alone test program. + */ +#ifdef TEST +#include +#include +#include +#include +#include +#include +#include + + /* + * Test cases. Note: the input and exp_output fields are converted with + * unescape(). Embedded null bytes must be specified as \\0. + */ +struct testcase { + const char *name; + const char *input; + const char *exp_output; + int exp_first_line; + int exp_last_line; +}; + +static const struct testcase testcases[] = { + {"leading space before non-comment", + " abcde\nfghij\n", + "fghij", + 2, 2 + /* Expect "logical line must not start with whitespace" */ + }, + {"leading space before leading comment", + " #abcde\nfghij\n", + "fghij", + 2, 2 + }, + {"leading #comment at beginning of line", + "#abc\ndef", + "def", + 2, 2, + }, + {"empty line before non-comment", + "\nabc\n", + "abc", + 2, 2, + }, + {"whitespace line before non-comment", + " \nabc\n", + "abc", + 2, 2, + }, + {"missing newline at end of non-comment", + "abc def", + "abc def", + 1, 1, + }, + {"missing newline at end of comment", + "#abc def", + "", + 1, 1, + }, + {"embedded null, single-line", + "abc\\0def", + "abc\\0def", + 1, 1, + /* Expect "line 1: text after null byte may be ignored" */ + }, + {"embedded null, multiline", + "abc\\0\n def", + "abc\\0 def", + 1, 2, + /* Expect "line 1-2: text after null byte may be ignored" */ + }, + {"embedded null in comment", + "#abc\\0\ndef", + "def", + 2, 2, + /* Expect "line 2: text after null byte may be ignored" */ + }, + {"multiline input", + "abc\n def\n", + "abc def", + 1, 2, + }, + {"multiline input with embedded #comment after space", + "abc\n #def\n ghi", + "abc ghi", + 1, 3, + }, + {"multiline input with embedded #comment flush left", + "abc\n#def\n ghi", + "abc ghi", + 1, 3, + }, + {"multiline input with embedded whitespace line", + "abc\n \n ghi", + "abc ghi", + 1, 3, + }, + {"multiline input with embedded empty line", + "abc\n\n ghi", + "abc ghi", + 1, 3, + }, + {"multiline input with embedded #comment after space", + "abc\n #def\n", + "abc", + 1, 2, + }, + {"multiline input with embedded #comment flush left", + "abc\n#def\n", + "abc", + 1, 2, + }, + {"empty line at end of file", + "\n", + "", + 1, 1, + }, + {"whitespace line at end of file", + "\n \n", + "", + 2, 2, + }, + {"whitespace at end of file", + "abc\n ", + "abc", + 1, 2, + }, +}; + +int main(int argc, char **argv) +{ + const struct testcase *tp; + VSTRING *inp_buf = vstring_alloc(100); + VSTRING *exp_buf = vstring_alloc(100); + VSTRING *out_buf = vstring_alloc(100); + VSTRING *esc_buf = vstring_alloc(100); + VSTREAM *fp; + int last_line; + int first_line; + int pass; + int fail; + +#define NUM_TESTS sizeof(testcases)/sizeof(testcases[0]) + + msg_vstream_init(basename(argv[0]), VSTREAM_ERR); + util_utf8_enable = 1; + + for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) { + int ok = 0; + + vstream_fprintf(VSTREAM_ERR, "RUN %s\n", tp->name); + unescape(inp_buf, tp->input); + unescape(exp_buf, tp->exp_output); + if ((fp = vstream_memopen(inp_buf, O_RDONLY)) == 0) + msg_panic("open memory stream for reading: %m"); + vstream_control(fp, CA_VSTREAM_CTL_PATH("memory buffer"), + CA_VSTREAM_CTL_END); + last_line = 0; + if (readllines(out_buf, fp, &last_line, &first_line) == 0) { + VSTRING_RESET(out_buf); + VSTRING_TERMINATE(out_buf); + } + if (LEN(out_buf) != LEN(exp_buf)) { + msg_warn("unexpected output length, got: %ld, want: %ld", + (long) LEN(out_buf), (long) LEN(exp_buf)); + } else if (memcmp(STR(out_buf), STR(exp_buf), LEN(out_buf)) != 0) { + msg_warn("unexpected output: got: >%s<, want: >%s<", + STR(escape(esc_buf, STR(out_buf), LEN(out_buf))), + tp->exp_output); + } else if (first_line != tp->exp_first_line) { + msg_warn("unexpected first_line: got: %d, want: %d", + first_line, tp->exp_first_line); + } else if (last_line != tp->exp_last_line) { + msg_warn("unexpected last_line: got: %d, want: %d", + last_line, tp->exp_last_line); + } else { + vstream_fprintf(VSTREAM_ERR, "got and want: >%s<\n", + tp->exp_output); + ok = 1; + } + if (ok) { + vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name); + pass++; + } else { + vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name); + fail++; + } + vstream_fclose(fp); + } + vstring_free(inp_buf); + vstring_free(exp_buf); + vstring_free(out_buf); + vstring_free(esc_buf); + + msg_info("PASS=%d FAIL=%d", pass, fail); + return (fail > 0); +} + +#endif diff --git a/src/util/stringops.h b/src/util/stringops.h index 97aa597..db56f23 100644 --- a/src/util/stringops.h +++ b/src/util/stringops.h @@ -60,10 +60,13 @@ extern int allascii_len(const char *, ssize_t); extern const char *WARN_UNUSED_RESULT split_nameval(char *, char **, char **); extern const char *WARN_UNUSED_RESULT split_qnameval(char *, char **, char **); extern int valid_utf8_string(const char *, ssize_t); +extern int valid_utf8_stringz(const char *); extern size_t balpar(const char *, const char *); extern char *WARN_UNUSED_RESULT extpar(char **, const char *, int); extern int strcasecmp_utf8x(int, const char *, const char *); extern int strncasecmp_utf8x(int, const char *, const char *, ssize_t); +extern char *quote_for_json(VSTRING *, const char *, ssize_t); +extern char *quote_for_json_append(VSTRING *, const char *, ssize_t); #define EXTPAR_FLAG_NONE (0) #define EXTPAR_FLAG_STRIP (1<<0) /* "{ text }" -> "text" */ diff --git a/src/util/sys_defs.h b/src/util/sys_defs.h index 9247185..62749ab 100644 --- a/src/util/sys_defs.h +++ b/src/util/sys_defs.h @@ -1331,6 +1331,13 @@ extern int dup2_pass_on_exec(int oldd, int newd); #undef HAVE_RES_SEND #endif + /* + * The RFC 5322 Date and Time Specification recommends single space between + * date-time tokens. To avoid breaking change, format all numerical days as + * two-digit days (i.e. days 1-9 now have a leading zero instead of space). + */ +#define TWO_DIGIT_DAY_IN_DATE_TIME + /* * Check for required but missing definitions. */ diff --git a/src/util/valid_hostname.c b/src/util/valid_hostname.c index 8b234c4..457d1f1 100644 --- a/src/util/valid_hostname.c +++ b/src/util/valid_hostname.c @@ -6,9 +6,9 @@ /* SYNOPSIS /* #include /* -/* int valid_hostname(name, gripe) +/* int valid_hostname(name, flags) /* const char *name; -/* int gripe; +/* int flags; /* /* int valid_hostaddr(addr, gripe) /* const char *addr; @@ -32,6 +32,10 @@ /* dots, no leading or trailing dots or hyphens, no labels /* longer than VALID_LABEL_LEN characters, and it should not /* be all numeric. +/* The flags argument is the bit-wise or of zero or more of +/* DO_GRIPE or DO_WILDCARD (the latter allows the "*." name +/* prefix, which is rare but valid in some DNS responses and +/* queries). /* /* valid_hostaddr() requires that the input is a valid string /* representation of an IPv4 or IPv6 network address as @@ -403,8 +407,9 @@ int main(int unused_argc, char **argv) while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { msg_info("testing: \"%s\"", vstring_str(buffer)); - valid_hostname(vstring_str(buffer), DO_GRIPE); - valid_hostaddr(vstring_str(buffer), DO_GRIPE); + valid_hostname(vstring_str(buffer), DO_GRIPE | DO_WILDCARD); + if (strchr(vstring_str(buffer), '*') == 0) + valid_hostaddr(vstring_str(buffer), DO_GRIPE); } exit(0); } diff --git a/src/util/valid_hostname.in b/src/util/valid_hostname.in index 608c0d1..4cdf019 100644 --- a/src/util/valid_hostname.in +++ b/src/util/valid_hostname.in @@ -53,3 +53,9 @@ g:a:a:a:a:a:a:a a::b :a::b a::b: +*.foo.bar +*foo.bar +foo.*.bar +foo*bar +foo.bar* +* diff --git a/src/util/valid_hostname.ref b/src/util/valid_hostname.ref index 08b23b8..eccc558 100644 --- a/src/util/valid_hostname.ref +++ b/src/util/valid_hostname.ref @@ -141,3 +141,13 @@ ./valid_hostname: testing: "a::b:" ./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a::b: ./valid_hostname: warning: valid_ipv6_hostaddr: bad null last field in IPv6 address: a::b: +./valid_hostname: testing: "*.foo.bar" +./valid_hostname: testing: "*foo.bar" +./valid_hostname: warning: valid_hostname: '*' can be the first label only: *foo.bar +./valid_hostname: testing: "foo.*.bar" +./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo.*.bar +./valid_hostname: testing: "foo*bar" +./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo*bar +./valid_hostname: testing: "foo.bar*" +./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo.bar* +./valid_hostname: testing: "*" diff --git a/src/util/valid_utf8_string.c b/src/util/valid_utf8_string.c index 96b5b4d..f5b4ff4 100644 --- a/src/util/valid_utf8_string.c +++ b/src/util/valid_utf8_string.c @@ -9,24 +9,24 @@ /* int valid_utf8_string(str, len) /* const char *str; /* ssize_t len; +/* +/* int valid_utf8_stringz(str) +/* const char *str; +/* ssize_t len; /* DESCRIPTION -/* valid_utf8_string() determines if a string satisfies the UTF-8 -/* definition in RFC 3629. That is, it contains proper encodings -/* of code points U+0000..U+10FFFF, excluding over-long encodings -/* and excluding U+D800..U+DFFF surrogates. +/* valid_utf8_string() determines if all bytes in a string +/* satisfy parse_utf8_char(3h) checks. See there for any +/* implementation limitations. +/* +/* valid_utf8_stringz() determines the same for zero-terminated +/* strings. /* /* A zero-length string is considered valid. /* DIAGNOSTICS /* The result value is zero when the caller specifies a negative -/* length, or a string that violates RFC 3629, for example a -/* string that is truncated in the middle of a multi-byte -/* sequence. -/* BUGS -/* But wait, there is more. Code points in the range U+FDD0..U+FDEF -/* and ending in FFFE or FFFF are non-characters in UNICODE. This -/* function does not block these. +/* length, or a string that does not pass parse_utf8_char(3h) checks. /* SEE ALSO -/* RFC 3629 +/* parse_utf8_char(3h), parse one UTF-8 multibyte character /* LICENSE /* .ad /* .fi @@ -36,6 +36,10 @@ /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA /*--*/ /* System library. */ @@ -45,66 +49,50 @@ /* Utility library. */ #include +#include /* valid_utf8_string - validate string according to RFC 3629 */ int valid_utf8_string(const char *str, ssize_t len) { - const unsigned char *end = (const unsigned char *) str + len; - const unsigned char *cp; - unsigned char c0, ch; + const char *ep = str + len; + const char *cp; + const char *last; if (len < 0) return (0); - if (len <= 0) + if (len == 0) return (1); /* - * Optimized for correct input, time, space, and for CPUs that have a - * decent number of registers. + * Ideally, the compiler will inline parse_utf8_char(). */ - for (cp = (const unsigned char *) str; cp < end; cp++) { - /* Single-byte encodings. */ - if (EXPECTED((c0 = *cp) <= 0x7f) /* we know that c0 >= 0x0 */ ) { - /* void */ ; - } - /* Two-byte encodings. */ - else if (EXPECTED(c0 <= 0xdf) /* we know that c0 >= 0x80 */ ) { - /* Exclude over-long encodings. */ - if (UNEXPECTED(c0 < 0xc2) - || UNEXPECTED(cp + 1 >= end) - /* Require UTF-8 tail byte. */ - || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) - return (0); - } - /* Three-byte encodings. */ - else if (EXPECTED(c0 <= 0xef) /* we know that c0 >= 0xe0 */ ) { - if (UNEXPECTED(cp + 2 >= end) - /* Exclude over-long encodings. */ - || UNEXPECTED((ch = *++cp) < (c0 == 0xe0 ? 0xa0 : 0x80)) - /* Exclude U+D800..U+DFFF. */ - || UNEXPECTED(ch > (c0 == 0xed ? 0x9f : 0xbf)) - /* Require UTF-8 tail byte. */ - || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) - return (0); - } - /* Four-byte encodings. */ - else if (EXPECTED(c0 <= 0xf4) /* we know that c0 >= 0xf0 */ ) { - if (UNEXPECTED(cp + 3 >= end) - /* Exclude over-long encodings. */ - || UNEXPECTED((ch = *++cp) < (c0 == 0xf0 ? 0x90 : 0x80)) - /* Exclude code points above U+10FFFF. */ - || UNEXPECTED(ch > (c0 == 0xf4 ? 0x8f : 0xbf)) - /* Require UTF-8 tail byte. */ - || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80) - /* Require UTF-8 tail byte. */ - || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) - return (0); - } - /* Invalid: c0 >= 0xf5 */ - else { + for (cp = str; cp < ep; cp++) { + if ((last = parse_utf8_char(cp, ep)) != 0) + cp = last; + else + return (0); + } + return (1); +} + +/* valid_utf8_stringz - validate string according to RFC 3629 */ + +int valid_utf8_stringz(const char *str) +{ + const char *cp; + const char *last; + + /* + * Ideally, the compiler will inline parse_utf8_char(), propagate the + * null pointer constant value, and eliminate code branches that test + * whether 0 != 0. + */ + for (cp = str; *cp; cp++) { + if ((last = parse_utf8_char(cp, 0)) != 0) + cp = last; + else return (0); - } } return (1); } @@ -114,26 +102,139 @@ int valid_utf8_string(const char *str, ssize_t len) */ #ifdef TEST #include +#include +#include #include -#include -#include +#include + + /* + * Test cases for 1-, 2-, and 3-byte encodings. See printable.c for UTF8 + * parser resychronization tests. + * + * XXX Need a test for 4-byte encodings, preferably with strings that can be + * displayed. + * + * XXX Need tests with hand-crafted over-long encodings and surrogates. + */ +struct testcase { + const char *name; + const char *input; + int expected; +}; -#define STR(x) vstring_str(x) -#define LEN(x) VSTRING_LEN(x) +#define T_VALID (1) +#define T_INVALID (0) +#define valid_to_str(v) ((v) ? "VALID" : "INVALID") -int main(void) +static const struct testcase testcases[] = { + {"Printable ASCII", + "printable", T_VALID, + }, + {"Latin script, accented, no error", + "na\303\257ve", T_VALID, + }, + {"Latin script, accented, missing non-leading byte", + "na\303ve", T_INVALID, + }, + {"Latin script, accented, missing leading byte", + "na\257ve", T_INVALID, + }, + {"Viktor, Cyrillic, no error", + "\320\262\320\270\320\272\321\202\320\276\321\200", T_VALID, + }, + {"Viktor, Cyrillic, missing non-leading byte", + "\320\262\320\320\272\321\202\320\276\321\200", T_INVALID, + }, + {"Viktor, Cyrillic, missing leading byte", + "\320\262\270\320\272\321\202\320\276\321\200", T_INVALID, + }, + {"Viktor, Cyrillic, truncated", + "\320\262\320\270\320\272\321\202\320\276\321", T_INVALID, + }, + {"Viktor, Hebrew, no error", + "\327\225\327\231\327\247\327\230\327\225\326\274\327\250", T_VALID, + }, + {"Viktor, Hebrew, missing leading byte", + "\327\225\231\327\247\327\230\327\225\326\274\327\250", T_INVALID, + }, + {"Chinese (Simplified), no error", + "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345\221\212", T_VALID, + }, + {"Chinese (Simplified), missing leading byte", + "\344\270\255\345\233\275\344\272\222\350\201\224\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345\221\212", T_INVALID, + }, + {"Chinese (Simplified), missing first non-leading byte", + "\344\270\255\345\233\275\344\272\222\350\201\224\347\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345\221\212", T_INVALID, + }, + {"Chinese (Simplified), missing second non-leading byte", + "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345\221\212", T_INVALID, + }, + {"Chinese (Simplified), truncated", + "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347" + "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273" + "\237\350\256\241\346\212\245\345", T_INVALID, + }, +}; + +int main(int argc, char **argv) { - VSTRING *buf = vstring_alloc(1); + const struct testcase *tp; + int pass; + int fail; + +#define NUM_TESTS sizeof(testcases)/sizeof(testcases[0]) + + msg_vstream_init(basename(argv[0]), VSTREAM_ERR); + util_utf8_enable = 1; + + for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) { + int actual_l; + int actual_z; + int ok = 0; - while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { - vstream_printf("%c", (LEN(buf) && !valid_utf8_string(STR(buf), LEN(buf))) ? - '!' : ' '); - vstream_fwrite(VSTREAM_OUT, STR(buf), LEN(buf)); - vstream_printf("\n"); + /* + * Notes: + * + * - The msg(3) functions use printable() which interferes when logging + * inputs and outputs. Use vstream_fprintf() instead. + */ + vstream_fprintf(VSTREAM_ERR, "RUN %s\n", tp->name); + actual_l = valid_utf8_string(tp->input, strlen(tp->input)); + actual_z = valid_utf8_stringz(tp->input); + + if (actual_l != tp->expected) { + vstream_fprintf(VSTREAM_ERR, + "input: >%s<, 'actual_l' got: >%s<, want: >%s<\n", + tp->input, valid_to_str(actual_l), + valid_to_str(tp->expected)); + } else if (actual_z != tp->expected) { + vstream_fprintf(VSTREAM_ERR, + "input: >%s<, 'actual_z' got: >%s<, want: >%s<\n", + tp->input, valid_to_str(actual_z), + valid_to_str(tp->expected)); + } else { + vstream_fprintf(VSTREAM_ERR, "input: >%s<, got and want: >%s<\n", + tp->input, valid_to_str(actual_l)); + ok = 1; + } + if (ok) { + vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name); + pass++; + } else { + vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name); + fail++; + } } - vstream_fflush(VSTREAM_OUT); - vstring_free(buf); - exit(0); + msg_info("PASS=%d FAIL=%d", pass, fail); + return (fail > 0); } #endif diff --git a/src/util/vstream.c b/src/util/vstream.c index b4f9fbb..affbcc0 100644 --- a/src/util/vstream.c +++ b/src/util/vstream.c @@ -522,6 +522,7 @@ /* System library. */ #include +#include #include /* 44BSD stdarg.h uses abort() */ #include #include @@ -1386,7 +1387,38 @@ VSTREAM *vstream_fopen(const char *path, int flags, mode_t mode) VSTREAM *stream; int fd; - if ((fd = open(path, flags, mode)) < 0) { + /* + * To set permissions on new files only, we need to distinguish between + * creating a new file and opening an existing one. + */ +#define open_create(path, flags, mode) \ + open((path), (flags) | (O_CREAT | O_EXCL), (mode)) +#define open_exist(path, flags, mode) \ + open((path), (flags) & ~(O_CREAT | O_EXCL), (mode)) + + switch (flags & (O_CREAT | O_EXCL)) { + case O_CREAT: + fd = open_exist(path, flags, mode); + if (fd < 0 && errno == ENOENT) { + fd = open_create(path, flags, mode); + if (fd >= 0) { + if (fchmod(fd, mode) < 0) /* can't uncreate */ + msg_warn("fchmod %s 0%o: %m", path, (unsigned) mode); + } else if ( /* fd < 0 && */ errno == EEXIST) + fd = open_exist(path, flags, mode); + } + break; + case O_CREAT | O_EXCL: + fd = open(path, flags, mode); + if (fd >= 0) + if (fchmod(fd, mode) < 0) /* can't uncreate */ + msg_warn("fchmod %s 0%o: %m", path, (unsigned) mode); + break; + default: + fd = open(path, flags, mode); + break; + } + if (fd < 0) { return (0); } else { stream = vstream_fdopen(fd, flags); diff --git a/src/xsasl/xsasl_cyrus_server.c b/src/xsasl/xsasl_cyrus_server.c index 4bf2ed2..e903289 100644 --- a/src/xsasl/xsasl_cyrus_server.c +++ b/src/xsasl/xsasl_cyrus_server.c @@ -52,6 +52,10 @@ /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA /*--*/ /* System library. */ diff --git a/src/xsasl/xsasl_server.c b/src/xsasl/xsasl_server.c index e8d7e16..c504864 100644 --- a/src/xsasl/xsasl_server.c +++ b/src/xsasl/xsasl_server.c @@ -123,7 +123,10 @@ /* reply. /* /* xsasl_server_get_username() returns the stored username -/* after successful authentication. +/* after successful authentication. The username may be null +/* after authentication failure, depending on the kind of +/* failure and on authentication backend implementation +/* details. A non-null result is converted to printable text. /* /* Arguments: /* .IP addr_family @@ -207,6 +210,10 @@ /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA +/* +/* Wietse Venema +/* porcupine.org +/* Amawalk, NY 10501, USA /*--*/ /* System library. */ -- cgit v1.2.3
    • Address manipulation Scope Daemon Global turn-on control Selective -turn-off control
      Daemon Turn-on controls +Turn-off controls
      Rewrite addresses to standard form all mail trivial-
      rewrite(8)
      receive_override_options nowrap> all mail cleanup(8) virtual_alias_maps receive_override_options
      Resolve address to destination - all mail trivial-
      rewrite(8)
      none none
      Mail transport switch all mail trivial-
      rewrite(8)
      -transport_maps none
      Resolve address to (transport, next-hop +destination) all mail +trivial-
      rewrite(8)
      local_transport, virtual_transport, +relay_transport, default_transport, relayhost, +sender_dependent_relayhost_maps, sender_dependent_default_transport_maps + content_filter
      Relocated users table all mail trivial-
      rewrite(8)
      @@ -774,6 +771,11 @@ may be a more appropriate vehicle. See the VIRTUAL_README document for an overview of methods to host virtual domains with Postfix.

      +

      Note: virtual aliasing (virtual_alias_maps) applies to all +recipients: local(8), virtual, and remote. +This is unlike local aliasing (alias_maps) which applies only to +local(8) recipients.

      +

      Virtual aliasing is disabled by default. To enable, edit the virtual_alias_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or @@ -833,9 +835,8 @@ trivial-rewrite(8) server.

        -
      • Resolve address to destination - -
      • Mail transport switch +
      • Resolve address to (transport, next-hop +destination)
      • Relocated users table @@ -873,67 +874,108 @@ via the local(8) delivery agent:

        step in more detail, with specific examples or with pointers to documentation with examples.

        -

        Resolve address to destination

        +

        Resolve address to (transport, next-hop +destination)

        The Postfix qmgr(8) queue manager selects new mail from the -incoming queue or old mail from the deferred queue, and asks the -trivial-rewrite(8) address rewriting and resolving daemon where it -should be delivered.

        +incoming queue or old mail from the deferred queue. First it +looks for overrides:

        + +
          -

          As of version 2.0, Postfix distinguishes four major address -classes. Each class has its own list of domain names, and each -class has its own default delivery method, as shown in the table -below. See the ADDRESS_CLASS_README document for the fine details. -Postfix versions before 2.0 only distinguish between local delivery -and everything else.

          +
        • The REDIRECT action in access(5), header_checks(5) or +body_checks(5) overrides all recipients of the message, and overrides +a content_filter setting, and FILTER action in access(5), +header_checks(5) or body_checks(5). The REDIRECT action was implemented +as a short-cut to retaliate for abuse.

          + +
        • A content_filter setting and FILTER action in access(5), +header_checks(5) or body_checks(5) provide their own (transport, +next-hop destination) information. This bypasses all the steps that +are described in the remainder of this section.

          + +
        + +

        When there is no content filter override, the qmgr(8) queue +manager asks the trivial-rewrite(8) address rewriting and resolving +daemon for each recipient how to deliver it (which message delivery +transport) and where to deliver it (what next-hop destination).

        + +

        As of version 2.0, Postfix distinguishes four major domain +classes. Each class has its own list of recipient domain names, and +each class has its own delivery method, as shown in the table below. +See the ADDRESS_CLASS_README document for the fine details. Postfix +versions before 2.0 only distinguish between local delivery and +everything else.

        + +

        Note that the table does not match recipients against +virtual_alias_domains. The reason is that all valid recipients in +a virtual alias domain must be aliased to an address in a different +domain. All other recipients in a virtual alias domain are by +definition undeliverable, and do not need to be considered here. +

        - + + - - + - - + + - + - - + +
        Destination domain list Default delivery method Availability -
        Domain class Recipient +domain match Delivery method Availability
        $mydestination, $inet_interfaces, $proxy_interfaces $local_transport Postfix 1.0
        Local mydestination, inet_interfaces, proxy_interfaces + local_transport Postfix 1.0
        $virtual_mailbox_domains $virtual_transport Postfix 2.0
        Virtual mailbox virtual_mailbox_domains virtual_transport Postfix 2.0
        $relay_domains $relay_transport Postfix -2.0
        Relay relay_domains relay_transport + Postfix 2.0
        none $default_transport Postfix 1.0
        Default none default_transport Postfix 1.0
        -

        Mail transport switch

        +

        The delivery methods in the above table may include a next-hop +destination in addition to a delivery transport. This may override +the next-hop destination that is by default taken from the recipient +domain.

        -

        Once the trivial-rewrite(8) daemon has determined a default -delivery method it searches the optional transport(5) table for -information that overrides the message destination and/or delivery -method. Typical use of the transport(5) table is to send mail to -a system -that is not connected to the Internet, or to use a special SMTP -client configuration for destinations that have special requirements. -See, for example, the STANDARD_CONFIGURATION_README and UUCP_README -documents, and the examples in the transport(5) manual page.

        +

        Over time, features have been added to override the above +transport and/or next-hop destination information. The following +table lists where a transport or next-hop destination may be taken +from, depending on the recipient domain class.

        -

        Transport table lookups are disabled by default. To enable, -edit the transport_maps parameter in the main.cf file and specify -one or more lookup tables, separated by whitespace or commas.

        +
        -

        Example:

        + + + + + + + + + + + + + + + +
        Domain class Transport sources (in order of +descending precedence) Next hop sources (in order of +descending precedence)
        Local transport_maps, local_transport transport_maps, local_transport, recipient domain
        Virtual mailbox transport_maps, +virtual_transport transport_maps, virtual_transport, +recipient domain
        Relay transport_maps, relay_transport transport_maps, relay_transport, sender_dependent_relayhost_maps, +relayhost, recipient domain
        Default transport_maps, +sender_dependent_default_transport_maps, default_transport transport_maps, sender_dependent_default_transport_maps, +default_transport, sender_dependent_relayhost_maps, relayhost, +recipient domain
        -
        -
        -/etc/postfix/main.cf:
        -    transport_maps = hash:/etc/postfix/transport
        -

        Relocated users table

        @@ -1019,6 +1061,11 @@ direct mail for standard aliases such as postmaster to real people. The table can also be used to map "Firstname.Lastname" addresses to login names.

        +

        Note: local aliasing (alias_maps) applies only to local(8) +recipients. This is unlike virtual aliasing (virtual_alias_maps) +which applies to all recipients: local(8), virtual, and remote. +

        +

        Alias lookups are enabled by default. The default configuration depends on the operating system environment, but it is typically one of the following:

        diff --git a/proto/COMPATIBILITY_README.html b/proto/COMPATIBILITY_README.html index e4e91e1..9f88927 100644 --- a/proto/COMPATIBILITY_README.html +++ b/proto/COMPATIBILITY_README.html @@ -61,24 +61,24 @@ default setting append_dot_mydomain=yes

      • Using backwards-compatible default setting chroot=y

        +
      • Using backwards-compatible +default setting "smtpd_relay_restrictions = (empty)"

        + +
      • Using backwards-compatible +default setting smtputf8_enable=no

        +

      Logged with compatibility_level < 2:

      Logged with compatibility_level < 3.6:

      @@ -241,6 +241,48 @@ administrator should make the backwards-compatible setting +

      Using backwards-compatible default +setting smtputf8_enable=no

      + +

      The smtputf8_enable default value has changed from "no" to "yes". +With the new "yes" setting, the Postfix SMTP server rejects non-ASCII +addresses from clients that don't request SMTPUTF8 support, after +Postfix is updated from an older version. The backwards-compatibility +safety net is designed to prevent such surprises.

      + +

      As long as the smtputf8_enable parameter is left at its implicit +default value, and the compatibility_level setting is +less than 1, Postfix logs a warning each time an SMTP command uses a +non-ASCII address localpart without requesting SMTPUTF8 support:

      + +
      +
      +postfix/smtpd[27560]: using backwards-compatible default setting
      +    smtputf8_enable=no to accept non-ASCII sender address
      +    "??@example.org" from localhost[127.0.0.1]
      +
      +
      + +
      +
      +postfix/smtpd[27560]: using backwards-compatible default setting
      +    smtputf8_enable=no to accept non-ASCII recipient address
      +    "??@example.com" from localhost[127.0.0.1]
      +
      +
      + +

      If the address should not be rejected, and the client cannot +be updated to use SMTPUTF8, then the system administrator should +make the backwards-compatible setting "smtputf8_enable = no" permanent +in main.cf: + +

      +
      +# postconf smtputf8_enable=no
      +# postfix reload
      +
      +
      +

      Using backwards-compatible default setting mynetworks_style=subnet

      @@ -352,48 +394,6 @@ administrator should make the backwards-compatible setting

      Instead of $mydestination, it may be better to specify an explicit list of domain names.

      -

      Using backwards-compatible default -setting smtputf8_enable=no

      - -

      The smtputf8_enable default value has changed from "no" to "yes". -With the new "yes" setting, the Postfix SMTP server rejects non-ASCII -addresses from clients that don't request SMTPUTF8 support, after -Postfix is updated from an older version. The backwards-compatibility -safety net is designed to prevent such surprises.

      - -

      As long as the smtputf8_enable parameter is left at its implicit -default value, and the compatibility_level setting is -less than 1, Postfix logs a warning each time an SMTP command uses a -non-ASCII address localpart without requesting SMTPUTF8 support:

      - -
      -
      -postfix/smtpd[27560]: using backwards-compatible default setting
      -    smtputf8_enable=no to accept non-ASCII sender address
      -    "??@example.org" from localhost[127.0.0.1]
      -
      -
      - -
      -
      -postfix/smtpd[27560]: using backwards-compatible default setting
      -    smtputf8_enable=no to accept non-ASCII recipient address
      -    "??@example.com" from localhost[127.0.0.1]
      -
      -
      - -

      If the address should not be rejected, and the client cannot -be updated to use SMTPUTF8, then the system administrator should -make the backwards-compatible setting "smtputf8_enable = no" permanent -in main.cf: - -

      -
      -# postconf smtputf8_enable=no
      -# postfix reload
      -
      -
      -

      Using backwards-compatible default setting smtpd_tls_fingerprint_digest=md5

      diff --git a/proto/DATABASE_README.html b/proto/DATABASE_README.html index 2302cc3..e9d0c18 100644 --- a/proto/DATABASE_README.html +++ b/proto/DATABASE_README.html @@ -59,7 +59,7 @@ documentation:

      alias_maps = hash:/etc/postfix/aliases (local aliasing) header_checks = regexp:/etc/postfix/header_checks (content filtering) transport_maps = hash:/etc/postfix/transport (routing table) - virtual_alias_maps = hash:/etc/postfix/virtual (address rewriting) + virtual_alias_maps = hash:/etc/postfix/virtual (virtual aliasing) @@ -349,6 +349,11 @@ ldap_table(5).
      Memcache database client. Configuration details are given in memcache_table(5).
      +
      mongodb (read-only)
      + +
      MongoDB database client. Configuration details are given in +mongodb_table(5), with examples in MONGODB_README.
      +
      mysql (read-only)
      MySQL database client. Configuration details are given in diff --git a/proto/DEPRECATION_README.html b/proto/DEPRECATION_README.html new file mode 100644 index 0000000..1ded555 --- /dev/null +++ b/proto/DEPRECATION_README.html @@ -0,0 +1,411 @@ + + + + + + +Postfix Replacements for Deprecated Features + + + + + + + + +

      Postfix +Replacements for Deprecated Features

      + +
      + +

      Purpose of this document

      + +

      This document describes Postfix features that are deprecated +(will be removed) or that have already been removed. It also has +tips for making an existing Postfix configuration more future-proof. +

      + +

      Overview:

      + + + +

      Why deprecate?

      + +

      Sometimes, a Postfix feature needs to be replaced with a different +one. To give an example:

      + +
        + +
      • The initial Postfix TLS implementation used multiple boolean +parameters: one parameter to enable opportunistic TLS (for example, +"smtp_enforce_tls = yes") and one parameter to enable mandatory TLS +(for example, "smtp_require_tls = yes").

        + +
      • As we added support more features such as fingerprint, +dane, and so on, we decided not to add more boolean parameters. +Instead we introduced one configuration parameter to select from +multiple deployment models (for example, smtp_tls_security_level = +may | encrypt | dane, etc...).

        + +
      + + + +

      Having both the "old" and "new" way to configure Postfix is +convenient for existing Postfix installations, because their +configuration does not break after an upgrade to a new version. +Unfortunately, there are also disadvantages. Having multiple ways +to do similar things is not only confusing for newcomers, it also +makes Postfix harder to change.

      + +

      Deprecation process

      + +

      The basic process steps are:

      + +
        + +
      1. Inform humans that a feature will be removed, and suggest +replacements, in logging and documentation.

        + +
      2. Remove the feature, and update logging and documentation.

        + +
      + +

      Disclaimer: it has taken 20 years for some features to be +removed. This past is not a guarantee for the future.

      + +

      Deprecated features

      + +

      The table summarizes removed or deprecated features and +replacements. Click on the "obsolete feature" name for a more +detailed description.

      + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Obsolete feature name Warning as
      of version +
      Removed
      in version
      Replacement
      disable_dns_lookups + 3.9 - smtp_dns_support_level
      xxx_use_tls 3.9 - +xxx_tls_security_level
      xxx_enforce_tls + 3.9 - xxx_tls_security_level
      xxx_per_site 3.9 - +xxx_policy_maps
      +smtpd_tls_dh1024_param_file 3.9 - do not specify (leave at default) +
      smtpd_tls_eecdh_grade + 3.9 - do not specify (leave at default)
      permit_mx_backup 3.9 - +relay_domains
      check_relay_domains + 2.2 3.9 permit_mynetworks, reject_unauth_destination
      reject_maps_rbl 2.1 3.9 +reject_rbl_client
      permit_naked_ip_address + 2.0 3.9 + permit_mynetworks, permit_sasl_authenticated
      + +
      + +

      Obsolete DNS on/off configuration +

      + +

      The postconf(1) command logs the following:

      + +
        + +
      • support for parameter "disable_dns_lookups" will be removed; instead, specify "smtp_dns_support_level" + +
      + +

      Replace obsolete configuration with its replacement:

      + +
      + + + + + + + + + +
      Goal Obsolete configuration + Replacement configuration
      To disable DNS lookups in the Postfix SMTP/LMTP client + disable_dns_lookups = yes smtp_dns_support_level += disabled
      To enable DNS lookups in the Postfix SMTP/LMTP client +disable_dns_lookups = no +Leave smtp_dns_support_level at the implicit default which is empty, unless +you need a higher support level such as DNSSEC.
      + +
      + +

      Obsolete opportunistic TLS configuration +

      + +

      The postconf(1) command logs one of the following:

      + +
        + +
      • support for parameter "lmtp_use_tls" will be removed; instead, specify "lmtp_tls_security_level" + +
      • support for parameter "smtp_use_tls" will be removed; instead, specify "smtp_tls_security_level" + +
      • support for parameter "smtpd_use_tls" will be removed; instead, specify "smtpd_tls_security_level" + +
      + +

      There are similarly-named parameters and warnings for postscreen(8) +and tlsproxy(8), but those parameters should rarely be specified +by hand.

      + +

      Replace obsolete configuration with its replacement:

      + +
      + + + + + + + + + + +
      Goal Obsolete configuration Replacement configuration
      To turn off TLS xxx_use_tls = no xxx_security_level = none
      To turn on opportunistic TLS xxx_use_tls += yes xxx_security_level = may
      + +
      + +

      Obsolete mandatory TLS configuration +

      + +

      The postconf(1) command logs one of the following:

      + +
        + +
      • support for parameter "lmtp_enforce_tls" will be removed; instead, specify "lmtp_tls_security_level" + +
      • support for parameter "smtp_enforce_tls" will be removed; instead, specify "smtp_tls_security_level" + +
      • support for parameter "smtpd_enforce_tls" will be removed; instead, specify "smtpd_tls_security_level" + +
      + +

      There are similarly-named parameters and warnings for postscreen(8) +and tlsproxy(8), but those parameters should rarely be specified +by hand.

      + +

      Replace obsolete configuration with its replacement:

      + +
      + + + + + + + + + +
      Goal Obsolete configuration Replacement configuration
      To turn off mandatory TLS xxx_enforce_tls += no xxx_security_level = may
      To turn on mandatory TLS xxx_enforce_tls += yes xxx_security_level = encrypt
      + +
      + +

      Obsolete TLS policy table configuration +

      + +

      The postconf(1) command logs one of the following:

      + +
        + +
      • support for parameter "lmtp_tls_per_site" will be removed; +instead, specify "lmtp_tls_policy_maps" + +
      • support for parameter "smtp_tls_per_site" will be removed; +instead, specify "smtp_tls_policy_maps" + +
      + +

      There is similarly-named parameter and warning for tlsproxy(8), +but that parameter should rarely be specified by hand.

      + +

      Unfortunately, this is more than a name change: the table format +has changed too, as has the table search process. There is no simple +conversion of the obsolete form to its replacement.

      + +

      check_relay_domains

      + +

      Depending on the Postfix version, the Postfix SMTP daemon logs +following warning:

      + +
        + +
      • support for restriction "check_relay_domains" has been removed +in Postfix 3.9"; instead, specify "reject_unauth_destination" + +
      • support for restriction "check_relay_domains" will be removed +from Postfix; use "reject_unauth_destination" instead + +
      + +

      This feature was removed because it would relay based on the +client domain name, which is not robust.

      + +

      Recommended configuration to prevent an "open relay" problem +with the SMTP service on port 25: +

      + +
      +
      +main.cf:
      +    smtpd_recipient_restrictions = 
      +	permit_mynetworks, 
      +	permit_sasl_authenticated, 
      +	reject_unauth_destination
      +	...other restrictions...
      +
      +
      + +

      Or equivalent in smtpd_relay_restrictions.

      + +

      permit_mx_backup

      + +

      The Postfix version 3.9 and later SMTP daemon logs the following +warning:

      + +
        + +
      • support for restriction "permit_mx_backup" will be removed +from Postfix; instead, specify "relay_domains" + +
      + +

      This feature will be removed because it is too difficult to +configure recipient address validation, making Postfix a source of +backscatter bounces.

      + +

      To specify the domains that Postfix will provide MX backup +service for, see +Configuring Postfix as primary or backup MX host for a remote +site.

      + +

      reject_maps_rbl

      + +

      Depending on the Postfix version, the SMTP daemon logs one of +the following warnings:

      + +
        + +
      • support for restriction "reject_maps_rbl" has been removed in +Postfix 3.9"; instead, specify "reject_rbl_client domain-name" + +
      • support for restriction "reject_maps_rbl" will be removed from +Postfix; use "reject_rbl_client domain-name" instead + +
      + +

      This feature was replaced because "MAPS RBL" is the name of a +specific reputation service. The reject_rbl_client feature provides +a superset of the reject_maps_rbl functionality.

      + +

      Recommended configuration:

      + +
      +
      +main.cf:
      +    smtpd_recipient_restrictions =
      +        permit_mynetworks,
      +        permit_sasl_authenticated,
      +        reject_unauth_destination
      +	reject_rbl_client domain-name
      +	...other restrictions...
      +
      +
      + +

      Where domain-name is the domain name of a DNS reputation service.

      + +

      permit_naked_ip_address

      + +

      Depending on the Postfix version, the SMTP daemon logs one of +the following warnings:

      + +
        + +
      • support for restriction "permit_naked_ip_address" has been +removed in Postfix 3.9"; instead, specify "permit_mynetworks" or +"permit_sasl_authenticated" + +
      • restriction permit_naked_ip_address is deprecated. Use +permit_mynetworks or permit_sasl_authenticated instead + +
      + +

      This feature was removed because it was easy to get a false +match when smtpd_recipient_restrictions was intended to match a +remote SMTP client IP address.

      + +

      Recommended configuration:

      + +
      +
      +main.cf:
      +    smtpd_recipient_restrictions =
      +        permit_mynetworks,
      +        permit_sasl_authenticated,
      +        reject_unauth_destination
      +        reject_rbl_client domain-name
      +        ...other restrictions...
      +
      +
      + +

      That is, no restriction on HELO or EHLO syntax. Such restrictions +ar rarely useful nowadays. + + + + diff --git a/proto/INSTALL.html b/proto/INSTALL.html index 4686f03..50249b2 100644 --- a/proto/INSTALL.html +++ b/proto/INSTALL.html @@ -605,6 +605,9 @@ describe how to build Postfix with support for optional features:

      LDAP database LDAP_README Postfix 1.0
      MongoDB database MONGODB_README Postfix +3.9
      MySQL database MYSQL_README Postfix 1.0